diff options
69 files changed, 1108 insertions, 392 deletions
diff --git a/build/all.gyp b/build/all.gyp index ebde11c..fde8461 100644 --- a/build/all.gyp +++ b/build/all.gyp @@ -51,11 +51,6 @@ '../chrome_frame/chrome_frame.gyp:*', ], }], - ['enable_gpu==1', { - 'dependencies': [ - '../gpu/gpu.gyp:*', - ], - }], ['OS=="mac" or OS=="linux" or OS=="freebsd"', { 'dependencies': [ '../third_party/yasm/yasm.gyp:*#host', @@ -100,6 +95,7 @@ '../chrome/app/locales/locales.gyp:*', '../courgette/courgette.gyp:*', '../gears/gears.gyp:*', + '../gpu/gpu.gyp:*', '../rlz/rlz.gyp:*', '../sandbox/sandbox.gyp:*', '../third_party/bsdiff/bsdiff.gyp:*', diff --git a/build/common.gypi b/build/common.gypi index a8ef21a..1d4da45 100644 --- a/build/common.gypi +++ b/build/common.gypi @@ -126,7 +126,7 @@ # JavaScript engines. 'javascript_engine%': 'v8', - # Although base/allocator lets you select a heap library via an + # Although base/allocator lets you select a heap library via an # environment variable, the libcmt shim it uses sometimes gets in # the way. To disable it entirely, and switch to normal msvcrt, do e.g. # 'win_use_allocator_shim': 0, @@ -327,9 +327,6 @@ ['chromeos==1 or toolkit_views==1', { 'defines': ['OS_CHROMEOS=1'], }], - ['enable_gpu==1', { - 'defines': ['ENABLE_GPU=1'], - }], ['fastbuild!=0', { 'conditions': [ # Finally, for Windows, we simply turn on profiling. @@ -355,6 +352,11 @@ }], ], }], + ['OS=="win"', { + 'defines': [ + 'ENABLE_GPU=1', + ], + }], ['coverage!=0', { 'conditions': [ ['OS=="mac"', { @@ -507,8 +509,8 @@ }], ['win_release_RuntimeLibrary==2', { # Visual C++ 2008 barfs when building anything with /MD (msvcrt): - # VC\include\typeinfo(139) : warning C4275: non dll-interface - # class 'stdext::exception' used as base for dll-interface + # VC\include\typeinfo(139) : warning C4275: non dll-interface + # class 'stdext::exception' used as base for dll-interface # class 'std::bad_cast' 'msvs_disabled_warnings': [4275], }], 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() { diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc index 3d3f9af..45c0866 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper.cc @@ -9,8 +9,6 @@ namespace gpu { -using gpu::CommandBuffer; - CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer) : command_buffer_(command_buffer), entries_(NULL), @@ -23,14 +21,10 @@ CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer) bool CommandBufferHelper::Initialize() { ring_buffer_ = command_buffer_->GetRingBuffer(); - if (!ring_buffer_) - return false; - - // Map the ring buffer into this process. - if (!ring_buffer_->Map(ring_buffer_->max_size())) + if (!ring_buffer_.ptr) return false; - entries_ = static_cast<CommandBufferEntry*>(ring_buffer_->memory()); + entries_ = static_cast<CommandBufferEntry*>(ring_buffer_.ptr); entry_count_ = command_buffer_->GetSize(); get_ = command_buffer_->GetGetOffset(); put_ = command_buffer_->GetPutOffset(); diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h index 1f191f1..6c134fa 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.h +++ b/gpu/command_buffer/client/cmd_buffer_helper.h @@ -31,7 +31,7 @@ namespace gpu { // // commands have been executed. class CommandBufferHelper { public: - explicit CommandBufferHelper(gpu::CommandBuffer* command_buffer); + explicit CommandBufferHelper(CommandBuffer* command_buffer); virtual ~CommandBufferHelper(); bool Initialize(); @@ -170,8 +170,8 @@ class CommandBufferHelper { return (get_ - put_ - 1 + entry_count_) % entry_count_; } - gpu::CommandBuffer* command_buffer_; - ::base::SharedMemory* ring_buffer_; + CommandBuffer* command_buffer_; + Buffer ring_buffer_; CommandBufferEntry *entries_; int32 entry_count_; int32 token_; diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc index 4c915fc..6c8fa6c 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper_test.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc @@ -14,8 +14,6 @@ namespace gpu { -using gpu::CommandBufferService; -using gpu::GPUProcessor; using testing::Return; using testing::Mock; using testing::Truly; @@ -41,16 +39,15 @@ class CommandBufferHelperTest : public testing::Test { .WillRepeatedly(Return(parse_error::kParseNoError)); command_buffer_.reset(new CommandBufferService); - base::SharedMemory* ring_buffer = command_buffer_->Initialize( - kNumCommandEntries); + command_buffer_->Initialize(kNumCommandEntries); + Buffer ring_buffer = command_buffer_->GetRingBuffer(); - - parser_ = new gpu::CommandParser(ring_buffer->memory(), - kCommandBufferSizeBytes, - 0, - kCommandBufferSizeBytes, - 0, - api_mock_.get()); + parser_ = new CommandParser(ring_buffer.ptr, + ring_buffer.size, + 0, + ring_buffer.size, + 0, + api_mock_.get()); scoped_refptr<GPUProcessor> gpu_processor(new GPUProcessor( command_buffer_.get(), NULL, parser_, 1)); @@ -111,7 +108,7 @@ class CommandBufferHelperTest : public testing::Test { MessageLoop message_loop_; scoped_ptr<AsyncAPIMock> api_mock_; scoped_ptr<CommandBufferService> command_buffer_; - gpu::CommandParser* parser_; + CommandParser* parser_; scoped_ptr<CommandBufferHelper> helper_; Sequence sequence_; }; diff --git a/gpu/command_buffer/client/fenced_allocator.h b/gpu/command_buffer/client/fenced_allocator.h index 83584c4..ab68c1a 100644 --- a/gpu/command_buffer/client/fenced_allocator.h +++ b/gpu/command_buffer/client/fenced_allocator.h @@ -128,7 +128,7 @@ class FencedAllocator { // the other functions that return a block index). Offset AllocInBlock(BlockIndex index, unsigned int size); - gpu::CommandBufferHelper *helper_; + CommandBufferHelper *helper_; Container blocks_; DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocator); diff --git a/gpu/command_buffer/client/fenced_allocator_test.cc b/gpu/command_buffer/client/fenced_allocator_test.cc index 4c621fa..a086463 100644 --- a/gpu/command_buffer/client/fenced_allocator_test.cc +++ b/gpu/command_buffer/client/fenced_allocator_test.cc @@ -16,8 +16,6 @@ namespace gpu { -using gpu::CommandBufferService; -using gpu::GPUProcessor; using testing::Return; using testing::Mock; using testing::Truly; @@ -42,15 +40,15 @@ class BaseFencedAllocatorTest : public testing::Test { Return(parse_error::kParseNoError))); command_buffer_.reset(new CommandBufferService); - base::SharedMemory* ring_buffer = command_buffer_->Initialize( - kBufferSize / sizeof(CommandBufferEntry)); + command_buffer_->Initialize(kBufferSize / sizeof(CommandBufferEntry)); + Buffer ring_buffer = command_buffer_->GetRingBuffer(); - parser_ = new gpu::CommandParser(ring_buffer->memory(), - kBufferSize, - 0, - kBufferSize, - 0, - api_mock_.get()); + parser_ = new CommandParser(ring_buffer.ptr, + ring_buffer.size, + 0, + ring_buffer.size, + 0, + api_mock_.get()); scoped_refptr<GPUProcessor> gpu_processor(new GPUProcessor( command_buffer_.get(), NULL, parser_, INT_MAX)); @@ -71,7 +69,7 @@ class BaseFencedAllocatorTest : public testing::Test { MessageLoop message_loop_; scoped_ptr<AsyncAPIMock> api_mock_; scoped_ptr<CommandBufferService> command_buffer_; - gpu::CommandParser* parser_; + CommandParser* parser_; scoped_ptr<CommandBufferHelper> helper_; }; diff --git a/gpu/command_buffer/client/gles2_cmd_helper.h b/gpu/command_buffer/client/gles2_cmd_helper.h index 383e7e5..015ce0e 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper.h +++ b/gpu/command_buffer/client/gles2_cmd_helper.h @@ -14,7 +14,7 @@ namespace gles2 { // A class that helps write GL command buffers. class GLES2CmdHelper : public CommandBufferHelper { public: - explicit GLES2CmdHelper(gpu::CommandBuffer* command_buffer) + explicit GLES2CmdHelper(CommandBuffer* command_buffer) : CommandBufferHelper(command_buffer) { } virtual ~GLES2CmdHelper() { diff --git a/gpu/command_buffer/client/gles2_demo.cc b/gpu/command_buffer/client/gles2_demo.cc index 465aa83..5b99f01 100644 --- a/gpu/command_buffer/client/gles2_demo.cc +++ b/gpu/command_buffer/client/gles2_demo.cc @@ -25,6 +25,7 @@ #include "gpu/command_buffer/client/gles2_demo_cc.h" using base::SharedMemory; +using gpu::Buffer; using gpu::GPUProcessor; using gpu::CommandBufferService; using gpu::gles2::GLES2CmdHelper; @@ -45,9 +46,8 @@ GLES2Demo::GLES2Demo() { bool GLES2Demo::Setup(void* hwnd, int32 size) { scoped_ptr<CommandBufferService> command_buffer(new CommandBufferService); - if (!command_buffer->Initialize(size)) { + if (!command_buffer->Initialize(size)) return NULL; - } scoped_refptr<GPUProcessor> gpu_processor( new GPUProcessor(command_buffer.get())); @@ -67,19 +67,15 @@ bool GLES2Demo::Setup(void* hwnd, int32 size) { size_t transfer_buffer_size = 512 * 1024; int32 transfer_buffer_id = command_buffer->CreateTransferBuffer(transfer_buffer_size); - ::base::SharedMemory* shared_memory = + Buffer transfer_buffer = command_buffer->GetTransferBuffer(transfer_buffer_id); - if (!shared_memory->Map(transfer_buffer_size)) { - return false; - } - void* transfer_buffer = shared_memory->memory(); - if (!transfer_buffer) { + if (!transfer_buffer.ptr) return false; - } + gles2::g_gl_impl = new GLES2Implementation(helper, - transfer_buffer_size, - transfer_buffer, + transfer_buffer.size, + transfer_buffer.ptr, transfer_buffer_id); return command_buffer.release() != NULL; diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index 6cdf22e..6415d67 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -5,7 +5,6 @@ #ifndef GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_H_ #define GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_H_ -#include "base/shared_memory.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/id_allocator.h" diff --git a/gpu/command_buffer/client/id_allocator.h b/gpu/command_buffer/client/id_allocator.h index 2b78f98..2731366 100644 --- a/gpu/command_buffer/client/id_allocator.h +++ b/gpu/command_buffer/client/id_allocator.h @@ -21,19 +21,19 @@ class IdAllocator { IdAllocator(); // Allocates a new resource ID. - gpu::ResourceId AllocateID() { + ResourceId AllocateID() { unsigned int bit = FindFirstFree(); SetBit(bit, true); return bit; } // Frees a resource ID. - void FreeID(gpu::ResourceId id) { + void FreeID(ResourceId id) { SetBit(id, false); } // Checks whether or not a resource ID is in use. - bool InUse(gpu::ResourceId id) { + bool InUse(ResourceId id) { return GetBit(id); } private: diff --git a/gpu/command_buffer/client/id_allocator_test.cc b/gpu/command_buffer/client/id_allocator_test.cc index d764f01..df457db 100644 --- a/gpu/command_buffer/client/id_allocator_test.cc +++ b/gpu/command_buffer/client/id_allocator_test.cc @@ -9,8 +9,6 @@ namespace gpu { -using gpu::ResourceId; - class IdAllocatorTest : public testing::Test { protected: virtual void SetUp() {} diff --git a/gpu/command_buffer/common/buffer.h b/gpu/command_buffer/common/buffer.h new file mode 100644 index 0000000..ed3cdf5 --- /dev/null +++ b/gpu/command_buffer/common/buffer.h @@ -0,0 +1,29 @@ +// 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 GPU_COMMAND_BUFFER_COMMON_BUFFER_H_ +#define GPU_COMMAND_BUFFER_COMMON_BUFFER_H_ + +namespace base { + class SharedMemory; +} + +namespace gpu { + +// Address and size of a buffer and optionally a shared memory object. This +// type has value semantics. +struct Buffer { + Buffer() : ptr(NULL), size(0), shared_memory(NULL) { + } + + void* ptr; + size_t size; + + // Null if the buffer is not shared memory or if it is not exposed as such. + base::SharedMemory* shared_memory; +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_COMMON_BUFFER_H_ diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h index 92e38ff..0f1f0f3 100644 --- a/gpu/command_buffer/common/command_buffer.h +++ b/gpu/command_buffer/common/command_buffer.h @@ -5,8 +5,8 @@ #ifndef GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_H_ #define GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_H_ -#include "base/shared_memory.h" #include "base/task.h" +#include "gpu/command_buffer/common/buffer.h" namespace gpu { @@ -21,10 +21,10 @@ class CommandBuffer { // Initialize the command buffer with the given size (number of command // entries). - virtual base::SharedMemory* Initialize(int32 size) = 0; + virtual bool Initialize(int32 size) = 0; - // Gets the shared memory ring buffer object for the command buffer. - virtual base::SharedMemory* GetRingBuffer() = 0; + // Gets the ring buffer for the command buffer. + virtual Buffer GetRingBuffer() = 0; virtual int32 GetSize() = 0; @@ -54,15 +54,15 @@ class CommandBuffer { // Takes ownership of callback. The callback is invoked on the plugin thread. virtual void SetPutOffsetChangeCallback(Callback0::Type* callback) = 0; - // Create a shared memory transfer buffer and return a handle that uniquely + // Create a transfer buffer and return a handle that uniquely // identifies it or -1 on error. virtual int32 CreateTransferBuffer(size_t size) = 0; - // Destroy a shared memory transfer buffer and recycle the handle. + // Destroy a transfer buffer and recycle the handle. virtual void DestroyTransferBuffer(int32 id) = 0; - // Get the shared memory associated with a handle. - virtual base::SharedMemory* GetTransferBuffer(int32 handle) = 0; + // Get the transfer buffer associated with a handle. + virtual Buffer GetTransferBuffer(int32 handle) = 0; // Get the current token value. This is used for by the writer to defer // changes to shared memory objects until the reader has reached a certain diff --git a/gpu/command_buffer/common/command_buffer_mock.h b/gpu/command_buffer/common/command_buffer_mock.h index 79d5682..0048ac1 100644 --- a/gpu/command_buffer/common/command_buffer_mock.h +++ b/gpu/command_buffer/common/command_buffer_mock.h @@ -16,13 +16,13 @@ class MockCommandBuffer : public CommandBuffer { public: MockCommandBuffer() { ON_CALL(*this, GetRingBuffer()) - .WillByDefault(testing::Return(static_cast<base::SharedMemory*>(NULL))); + .WillByDefault(testing::Return(Buffer())); ON_CALL(*this, GetTransferBuffer(testing::_)) - .WillByDefault(testing::Return(static_cast<base::SharedMemory*>(NULL))); + .WillByDefault(testing::Return(Buffer())); } - MOCK_METHOD1(Initialize, base::SharedMemory*(int32 size)); - MOCK_METHOD0(GetRingBuffer, base::SharedMemory*()); + MOCK_METHOD1(Initialize, bool(int32 size)); + MOCK_METHOD0(GetRingBuffer, Buffer()); MOCK_METHOD0(GetSize, int32()); MOCK_METHOD1(SyncOffsets, int32(int32 put_offset)); MOCK_METHOD0(GetGetOffset, int32()); @@ -31,7 +31,7 @@ class MockCommandBuffer : public CommandBuffer { MOCK_METHOD1(SetPutOffsetChangeCallback, void(Callback0::Type* callback)); MOCK_METHOD1(CreateTransferBuffer, int32(size_t size)); MOCK_METHOD1(DestroyTransferBuffer, void(int32 handle)); - MOCK_METHOD1(GetTransferBuffer, base::SharedMemory*(int32 handle)); + MOCK_METHOD1(GetTransferBuffer, Buffer(int32 handle)); MOCK_METHOD0(GetToken, int32()); MOCK_METHOD1(SetToken, void(int32 token)); MOCK_METHOD0(ResetParseError, int32()); diff --git a/gpu/command_buffer/common/gles2_cmd_format.h b/gpu/command_buffer/common/gles2_cmd_format.h index 8b37982..e6f2b78 100644 --- a/gpu/command_buffer/common/gles2_cmd_format.h +++ b/gpu/command_buffer/common/gles2_cmd_format.h @@ -69,7 +69,7 @@ struct GetAttribLocation { return NextCmdAddress<ValueType>(cmd); } - gpu::CommandHeader header; + CommandHeader header; uint32 program; uint32 name_shm_id; uint32 name_shm_offset; @@ -132,7 +132,7 @@ struct GetAttribLocationImmediate { return NextImmediateCmdAddressTotalSize<ValueType>(cmd, total_size); } - gpu::CommandHeader header; + CommandHeader header; uint32 program; uint32 location_shm_id; uint32 location_shm_offset; @@ -189,7 +189,7 @@ struct GetUniformLocation { return NextCmdAddress<ValueType>(cmd); } - gpu::CommandHeader header; + CommandHeader header; uint32 program; uint32 name_shm_id; uint32 name_shm_offset; @@ -252,7 +252,7 @@ struct GetUniformLocationImmediate { return NextImmediateCmdAddressTotalSize<ValueType>(cmd, total_size); } - gpu::CommandHeader header; + CommandHeader header; uint32 program; uint32 location_shm_id; uint32 location_shm_offset; diff --git a/gpu/command_buffer/common/resource.h b/gpu/command_buffer/common/resource.h index 2dae7df..f72395a 100644 --- a/gpu/command_buffer/common/resource.h +++ b/gpu/command_buffer/common/resource.h @@ -10,7 +10,6 @@ #include <algorithm> #include "base/basictypes.h" -#include "base/scoped_ptr.h" #include "gpu/command_buffer/common/types.h" #include "gpu/command_buffer/common/logging.h" diff --git a/gpu/command_buffer/service/cmd_buffer_engine.h b/gpu/command_buffer/service/cmd_buffer_engine.h index 7457a2f..09419a0 100644 --- a/gpu/command_buffer/service/cmd_buffer_engine.h +++ b/gpu/command_buffer/service/cmd_buffer_engine.h @@ -9,6 +9,7 @@ #define GPU_COMMAND_BUFFER_SERVICE_CMD_BUFFER_ENGINE_H_ #include "base/basictypes.h" +#include "gpu/command_buffer/common/buffer.h" namespace gpu { @@ -20,15 +21,10 @@ class CommandBufferEngine { virtual ~CommandBufferEngine() { } - // Gets the base address of a registered shared memory buffer. + // Gets the base address and size of a registered shared memory buffer. // Parameters: // shm_id: the identifier for the shared memory buffer. - virtual void *GetSharedMemoryAddress(int32 shm_id) = 0; - - // Gets the size of a registered shared memory buffer. - // Parameters: - // shm_id: the identifier for the shared memory buffer. - virtual size_t GetSharedMemorySize(int32 shm_id) = 0; + virtual Buffer GetSharedMemoryBuffer(int32 shm_id) = 0; // Sets the token value. virtual void set_token(int32 token) = 0; diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc index e2dffec..17e7a61 100644 --- a/gpu/command_buffer/service/command_buffer_service.cc +++ b/gpu/command_buffer/service/command_buffer_service.cc @@ -6,6 +6,8 @@ #include <limits> +#include "gpu/command_buffer/common/cmd_buffer_common.h" + using ::base::SharedMemory; namespace gpu { @@ -24,7 +26,7 @@ CommandBufferService::CommandBufferService() CommandBufferService::~CommandBufferService() { } -base::SharedMemory* CommandBufferService::Initialize(int32 size) { +bool CommandBufferService::Initialize(int32 size) { // Fail if already initialized. if (ring_buffer_.get()) return false; @@ -32,17 +34,24 @@ base::SharedMemory* CommandBufferService::Initialize(int32 size) { size_ = size; ring_buffer_.reset(new SharedMemory); - if (ring_buffer_->Create(std::wstring(), false, false, size_)) { - if (ring_buffer_->Map(size_)) - return ring_buffer_.get(); + size_t size_bytes = size * sizeof(CommandBufferEntry); + if (ring_buffer_->Create(std::wstring(), false, false, size_bytes)) { + if (ring_buffer_->Map(size_bytes)) + return true; } ring_buffer_.reset(); - return NULL; + return false; } -SharedMemory* CommandBufferService::GetRingBuffer() { - return ring_buffer_.get(); +Buffer CommandBufferService::GetRingBuffer() { + Buffer buffer; + if (ring_buffer_.get()) { + buffer.ptr = ring_buffer_->memory(); + buffer.size = ring_buffer_->max_size(); + buffer.shared_memory = ring_buffer_.get(); + } + return buffer; } int32 CommandBufferService::GetSize() { @@ -123,14 +132,27 @@ void CommandBufferService::DestroyTransferBuffer(int32 handle) { } } -::base::SharedMemory* CommandBufferService::GetTransferBuffer(int32 handle) { +Buffer CommandBufferService::GetTransferBuffer(int32 handle) { if (handle < 0) - return NULL; + return Buffer(); if (static_cast<size_t>(handle) >= registered_objects_.size()) - return NULL; + return Buffer(); + + base::SharedMemory* shared_memory = registered_objects_[handle].get(); + if (!shared_memory) + return Buffer(); + + if (!shared_memory->memory()) { + if (!shared_memory->Map(shared_memory->max_size())) + return Buffer(); + } - return registered_objects_[handle].get(); + Buffer buffer; + buffer.ptr = shared_memory->memory(); + buffer.size = shared_memory->max_size(); + buffer.shared_memory = shared_memory; + return buffer; } int32 CommandBufferService::GetToken() { diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h index 6784581..18860ea 100644 --- a/gpu/command_buffer/service/command_buffer_service.h +++ b/gpu/command_buffer/service/command_buffer_service.h @@ -24,8 +24,8 @@ class CommandBufferService : public CommandBuffer { virtual ~CommandBufferService(); // CommandBuffer implementation: - virtual base::SharedMemory* Initialize(int32 size); - virtual base::SharedMemory* GetRingBuffer(); + virtual bool Initialize(int32 size); + virtual Buffer GetRingBuffer(); virtual int32 GetSize(); virtual int32 SyncOffsets(int32 put_offset); virtual int32 GetGetOffset(); @@ -34,7 +34,7 @@ class CommandBufferService : public 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 Buffer GetTransferBuffer(int32 handle); virtual int32 GetToken(); virtual void SetToken(int32 token); virtual int32 ResetParseError(); diff --git a/gpu/command_buffer/service/command_buffer_service_unittest.cc b/gpu/command_buffer/service/command_buffer_service_unittest.cc index b5749af..98ec0ec 100644 --- a/gpu/command_buffer/service/command_buffer_service_unittest.cc +++ b/gpu/command_buffer/service/command_buffer_service_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/thread.h" +#include "gpu/command_buffer/common/cmd_buffer_common.h" #include "gpu/command_buffer/service/command_buffer_service.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gmock/include/gmock/gmock.h" @@ -26,20 +27,28 @@ class CommandBufferServiceTest : public testing::Test { }; TEST_F(CommandBufferServiceTest, NullRingBufferByDefault) { - EXPECT_TRUE(NULL == command_buffer_->GetRingBuffer()); + EXPECT_TRUE(NULL == command_buffer_->GetRingBuffer().ptr); } TEST_F(CommandBufferServiceTest, InitializesCommandBuffer) { - base::SharedMemory* ring_buffer = command_buffer_->Initialize(1024); - EXPECT_TRUE(NULL != ring_buffer); - EXPECT_EQ(ring_buffer, command_buffer_->GetRingBuffer()); - EXPECT_GT(command_buffer_->GetSize(), 0); + EXPECT_TRUE(command_buffer_->Initialize(1024)); + EXPECT_TRUE(NULL != command_buffer_->GetRingBuffer().ptr); + EXPECT_EQ(1024, command_buffer_->GetSize()); + EXPECT_EQ(1024 * sizeof(CommandBufferEntry), + command_buffer_->GetRingBuffer().size); +} + +TEST_F(CommandBufferServiceTest, InitializationSizeIsInEntriesNotBytes) { + EXPECT_TRUE(command_buffer_->Initialize(1024)); + EXPECT_TRUE(NULL != command_buffer_->GetRingBuffer().ptr); + EXPECT_GE(1024 * sizeof(CommandBufferEntry), + command_buffer_->GetRingBuffer().size); } TEST_F(CommandBufferServiceTest, InitializeFailsSecondTime) { SharedMemory* ring_buffer = new SharedMemory; - EXPECT_TRUE(NULL != command_buffer_->Initialize(1024)); - EXPECT_TRUE(NULL == command_buffer_->Initialize(1024)); + EXPECT_TRUE(command_buffer_->Initialize(1024)); + EXPECT_FALSE(command_buffer_->Initialize(1024)); } TEST_F(CommandBufferServiceTest, GetAndPutOffsetsDefaultToZero) { @@ -77,23 +86,23 @@ TEST_F(CommandBufferServiceTest, CanSyncGetAndPutOffset) { } TEST_F(CommandBufferServiceTest, ZeroHandleMapsToNull) { - EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(0)); + EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(0).ptr); } TEST_F(CommandBufferServiceTest, NegativeHandleMapsToNull) { - EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(-1)); + EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(-1).ptr); } TEST_F(CommandBufferServiceTest, OutOfRangeHandleMapsToNull) { - EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(1)); + EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(1).ptr); } TEST_F(CommandBufferServiceTest, CanCreateTransferBuffers) { int32 handle = command_buffer_->CreateTransferBuffer(1024); EXPECT_EQ(1, handle); - SharedMemory* buffer = command_buffer_->GetTransferBuffer(handle); - ASSERT_TRUE(NULL != buffer); - EXPECT_EQ(1024, buffer->max_size()); + Buffer buffer = command_buffer_->GetTransferBuffer(handle); + ASSERT_TRUE(NULL != buffer.ptr); + EXPECT_EQ(1024, buffer.size); } TEST_F(CommandBufferServiceTest, CreateTransferBufferReturnsDistinctHandles) { @@ -111,7 +120,7 @@ TEST_F(CommandBufferServiceTest, TEST_F(CommandBufferServiceTest, CannotUnregisterHandleZero) { command_buffer_->DestroyTransferBuffer(0); - EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(0)); + EXPECT_TRUE(NULL == command_buffer_->GetTransferBuffer(0).ptr); EXPECT_EQ(1, command_buffer_->CreateTransferBuffer(1024)); } diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc index 591dfb7..4d3623d 100644 --- a/gpu/command_buffer/service/common_decoder.cc +++ b/gpu/command_buffer/service/common_decoder.cc @@ -35,14 +35,14 @@ bool CommonDecoder::Bucket::SetData( void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id, unsigned int offset, unsigned int size) { - void* shm_addr = engine_->GetSharedMemoryAddress(shm_id); - if (!shm_addr) return NULL; - size_t shm_size = engine_->GetSharedMemorySize(shm_id); + Buffer buffer = engine_->GetSharedMemoryBuffer(shm_id); + if (!buffer.ptr) + return NULL; unsigned int end = offset + size; - if (end > shm_size || end < offset) { + if (end > buffer.size || end < offset) { return NULL; } - return static_cast<int8 *>(shm_addr) + offset; + return static_cast<int8*>(buffer.ptr) + offset; } const char* CommonDecoder::GetCommonCommandName( diff --git a/gpu/command_buffer/service/common_decoder_unittest.cc b/gpu/command_buffer/service/common_decoder_unittest.cc index 54f1941..9a2db70 100644 --- a/gpu/command_buffer/service/common_decoder_unittest.cc +++ b/gpu/command_buffer/service/common_decoder_unittest.cc @@ -78,13 +78,13 @@ class MockCommandBufferEngine : public CommandBufferEngine { } // Overridden from CommandBufferEngine. - virtual void* GetSharedMemoryAddress(int32 shm_id) { - return (shm_id == kValidShmId) ? buffer_ : NULL; - } - - // Overridden from CommandBufferEngine. - virtual size_t GetSharedMemorySize(int32 shm_id) { - return (shm_id == kValidShmId) ? kBufferSize : 0; + virtual Buffer GetSharedMemoryBuffer(int32 shm_id) { + Buffer buffer; + if (shm_id == kValidShmId) { + buffer.ptr = buffer_; + buffer.size = kBufferSize; + } + return buffer; } template <typename T> diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc index 61449c0..0968215 100644 --- a/gpu/command_buffer/service/gpu_processor.cc +++ b/gpu/command_buffer/service/gpu_processor.cc @@ -20,16 +20,15 @@ void GPUProcessor::ProcessCommands() { int commands_processed = 0; while (commands_processed < commands_per_update_ && !parser_->IsEmpty()) { - gpu::parse_error::ParseError parse_error = - parser_->ProcessCommand(); + parse_error::ParseError parse_error = parser_->ProcessCommand(); switch (parse_error) { - case gpu::parse_error::kParseUnknownCommand: - case gpu::parse_error::kParseInvalidArguments: + case parse_error::kParseUnknownCommand: + case parse_error::kParseInvalidArguments: command_buffer_->SetParseError(parse_error); break; - case gpu::parse_error::kParseInvalidSize: - case gpu::parse_error::kParseOutOfBounds: + case parse_error::kParseInvalidSize: + case parse_error::kParseOutOfBounds: command_buffer_->SetParseError(parse_error); command_buffer_->RaiseErrorStatus(); return; @@ -46,29 +45,8 @@ void GPUProcessor::ProcessCommands() { } } -void *GPUProcessor::GetSharedMemoryAddress(int32 shm_id) { - ::base::SharedMemory* shared_memory = - command_buffer_->GetTransferBuffer(shm_id); - if (!shared_memory) - return NULL; - - if (!shared_memory->memory()) { - if (!shared_memory->Map(shared_memory->max_size())) - return NULL; - } - - return shared_memory->memory(); -} - -// TODO(apatrick): Consolidate this with the above and return both the address -// and size. -size_t GPUProcessor::GetSharedMemorySize(int32 shm_id) { - ::base::SharedMemory* shared_memory = - command_buffer_->GetTransferBuffer(shm_id); - if (!shared_memory) - return 0; - - return shared_memory->max_size(); +Buffer GPUProcessor::GetSharedMemoryBuffer(int32 shm_id) { + return command_buffer_->GetTransferBuffer(shm_id); } void GPUProcessor::set_token(int32 token) { diff --git a/gpu/command_buffer/service/gpu_processor.h b/gpu/command_buffer/service/gpu_processor.h index a594f0b..41325fa 100644 --- a/gpu/command_buffer/service/gpu_processor.h +++ b/gpu/command_buffer/service/gpu_processor.h @@ -18,8 +18,8 @@ namespace gpu { // This class processes commands in a command buffer. It is event driven and // posts tasks to the current message loop to do additional work. -class GPUProcessor : public ::base::RefCounted<GPUProcessor>, - public gpu::CommandBufferEngine { +class GPUProcessor : public base::RefCounted<GPUProcessor>, + public CommandBufferEngine { public: explicit GPUProcessor(CommandBuffer* command_buffer); @@ -37,21 +37,8 @@ class GPUProcessor : public ::base::RefCounted<GPUProcessor>, virtual void ProcessCommands(); - virtual bool SetWindow(gfx::PluginWindowHandle handle, int width, int height); - // Implementation of CommandBufferEngine. - - // Gets the base address of a registered shared memory buffer. - // Parameters: - // shm_id: the identifier for the shared memory buffer. - virtual void *GetSharedMemoryAddress(int32 shm_id); - - // Gets the size of a registered shared memory buffer. - // Parameters: - // shm_id: the identifier for the shared memory buffer. - virtual size_t GetSharedMemorySize(int32 shm_id); - - // Sets the token value. + virtual Buffer GetSharedMemoryBuffer(int32 shm_id); virtual void set_token(int32 token); private: diff --git a/gpu/command_buffer/service/gpu_processor_mock.h b/gpu/command_buffer/service/gpu_processor_mock.h index be6a938..ca257e8 100644 --- a/gpu/command_buffer/service/gpu_processor_mock.h +++ b/gpu/command_buffer/service/gpu_processor_mock.h @@ -19,11 +19,7 @@ class MockGPUProcessor : public GPUProcessor { MOCK_METHOD1(Initialize, bool(gfx::PluginWindowHandle handle)); MOCK_METHOD0(Destroy, void()); MOCK_METHOD0(ProcessCommands, void()); - MOCK_METHOD3(SetWindow, bool(gfx::PluginWindowHandle handle, - int width, - int height)); - MOCK_METHOD1(GetSharedMemoryAddress, void*(int32 shm_id)); - MOCK_METHOD1(GetSharedMemorySize, size_t(int32 shm_id)); + MOCK_METHOD1(GetSharedMemoryBuffer, Buffer(int32 shm_id)); MOCK_METHOD1(set_token, void(int32 token)); private: diff --git a/gpu/command_buffer/service/gpu_processor_unittest.cc b/gpu/command_buffer/service/gpu_processor_unittest.cc index 5041371..304dc72 100644 --- a/gpu/command_buffer/service/gpu_processor_unittest.cc +++ b/gpu/command_buffer/service/gpu_processor_unittest.cc @@ -31,25 +31,26 @@ class GPUProcessorTest : public testing::Test { shared_memory_->Create(std::wstring(), false, false, kRingBufferSize); shared_memory_->Map(kRingBufferSize); buffer_ = static_cast<int32*>(shared_memory_->memory()); - + shared_memory_buffer_.ptr = buffer_; + shared_memory_buffer_.size = kRingBufferSize; memset(buffer_, 0, kRingBufferSize); command_buffer_.reset(new MockCommandBuffer); ON_CALL(*command_buffer_.get(), GetRingBuffer()) - .WillByDefault(Return(shared_memory_.get())); + .WillByDefault(Return(shared_memory_buffer_)); ON_CALL(*command_buffer_.get(), GetSize()) .WillByDefault(Return(kRingBufferEntries)); - async_api_.reset(new StrictMock<gpu::AsyncAPIMock>); + async_api_.reset(new StrictMock<AsyncAPIMock>); decoder_ = gles2::GLES2Decoder::Create(); - parser_ = new gpu::CommandParser(buffer_, - kRingBufferEntries, - 0, - kRingBufferEntries, - 0, - async_api_.get()); + parser_ = new CommandParser(buffer_, + kRingBufferEntries, + 0, + kRingBufferEntries, + 0, + async_api_.get()); processor_ = new GPUProcessor(command_buffer_.get(), decoder_, @@ -67,10 +68,11 @@ class GPUProcessorTest : public testing::Test { MessageLoop message_loop; scoped_ptr<MockCommandBuffer> command_buffer_; scoped_ptr<::base::SharedMemory> shared_memory_; + Buffer shared_memory_buffer_; int32* buffer_; - gpu::gles2::GLES2Decoder* decoder_; - gpu::CommandParser* parser_; - scoped_ptr<gpu::AsyncAPIMock> async_api_; + gles2::GLES2Decoder* decoder_; + CommandParser* parser_; + scoped_ptr<AsyncAPIMock> async_api_; scoped_refptr<GPUProcessor> processor_; }; @@ -81,14 +83,13 @@ TEST_F(GPUProcessorTest, ProcessorDoesNothingIfRingBufferIsEmpty) { processor_->ProcessCommands(); - EXPECT_EQ(gpu::parse_error::kParseNoError, + EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError()); EXPECT_FALSE(command_buffer_->GetErrorStatus()); } TEST_F(GPUProcessorTest, ProcessesOneCommand) { - gpu::CommandHeader* header = - reinterpret_cast<gpu::CommandHeader*>(&buffer_[0]); + CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]); header[0].command = 7; header[0].size = 2; buffer_[1] = 123; @@ -98,18 +99,17 @@ TEST_F(GPUProcessorTest, ProcessesOneCommand) { EXPECT_CALL(*command_buffer_, SetGetOffset(2)); EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0])) - .WillOnce(Return(gpu::parse_error::kParseNoError)); + .WillOnce(Return(parse_error::kParseNoError)); processor_->ProcessCommands(); - EXPECT_EQ(gpu::parse_error::kParseNoError, + EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError()); EXPECT_FALSE(command_buffer_->GetErrorStatus()); } TEST_F(GPUProcessorTest, ProcessesTwoCommands) { - gpu::CommandHeader* header = - reinterpret_cast<gpu::CommandHeader*>(&buffer_[0]); + CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]); header[0].command = 7; header[0].size = 2; buffer_[1] = 123; @@ -121,17 +121,16 @@ TEST_F(GPUProcessorTest, ProcessesTwoCommands) { EXPECT_CALL(*command_buffer_, SetGetOffset(3)); EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0])) - .WillOnce(Return(gpu::parse_error::kParseNoError)); + .WillOnce(Return(parse_error::kParseNoError)); EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[2])) - .WillOnce(Return(gpu::parse_error::kParseNoError)); + .WillOnce(Return(parse_error::kParseNoError)); processor_->ProcessCommands(); } TEST_F(GPUProcessorTest, PostsTaskToFinishRemainingCommands) { - gpu::CommandHeader* header = - reinterpret_cast<gpu::CommandHeader*>(&buffer_[0]); + CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]); header[0].command = 7; header[0].size = 2; buffer_[1] = 123; @@ -144,10 +143,10 @@ TEST_F(GPUProcessorTest, PostsTaskToFinishRemainingCommands) { .WillOnce(Return(4)); EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0])) - .WillOnce(Return(gpu::parse_error::kParseNoError)); + .WillOnce(Return(parse_error::kParseNoError)); EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[2])) - .WillOnce(Return(gpu::parse_error::kParseNoError)); + .WillOnce(Return(parse_error::kParseNoError)); EXPECT_CALL(*command_buffer_, SetGetOffset(3)); @@ -159,7 +158,7 @@ TEST_F(GPUProcessorTest, PostsTaskToFinishRemainingCommands) { .WillOnce(Return(4)); EXPECT_CALL(*async_api_, DoCommand(9, 0, &buffer_[3])) - .WillOnce(Return(gpu::parse_error::kParseNoError)); + .WillOnce(Return(parse_error::kParseNoError)); EXPECT_CALL(*command_buffer_, SetGetOffset(4)); @@ -167,8 +166,7 @@ TEST_F(GPUProcessorTest, PostsTaskToFinishRemainingCommands) { } TEST_F(GPUProcessorTest, SetsErrorCodeOnCommandBuffer) { - gpu::CommandHeader* header = - reinterpret_cast<gpu::CommandHeader*>(&buffer_[0]); + CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]); header[0].command = 7; header[0].size = 1; @@ -178,18 +176,17 @@ TEST_F(GPUProcessorTest, SetsErrorCodeOnCommandBuffer) { EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0])) .WillOnce(Return( - gpu::parse_error::kParseUnknownCommand)); + parse_error::kParseUnknownCommand)); EXPECT_CALL(*command_buffer_, - SetParseError(gpu::parse_error::kParseUnknownCommand)); + SetParseError(parse_error::kParseUnknownCommand)); processor_->ProcessCommands(); } TEST_F(GPUProcessorTest, RecoverableParseErrorsAreNotClearedByFollowingSuccessfulCommands) { - gpu::CommandHeader* header = - reinterpret_cast<gpu::CommandHeader*>(&buffer_[0]); + CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]); header[0].command = 7; header[0].size = 1; header[1].command = 8; @@ -201,20 +198,20 @@ TEST_F(GPUProcessorTest, EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0])) .WillOnce(Return( - gpu::parse_error::kParseUnknownCommand)); + parse_error::kParseUnknownCommand)); EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[1])) - .WillOnce(Return(gpu::parse_error::kParseNoError)); + .WillOnce(Return(parse_error::kParseNoError)); EXPECT_CALL(*command_buffer_, - SetParseError(gpu::parse_error::kParseUnknownCommand)); + SetParseError(parse_error::kParseUnknownCommand)); processor_->ProcessCommands(); } TEST_F(GPUProcessorTest, UnrecoverableParseErrorsRaiseTheErrorStatus) { - gpu::CommandHeader* header = - reinterpret_cast<gpu::CommandHeader*>(&buffer_[0]); + CommandHeader* header = + reinterpret_cast<CommandHeader*>(&buffer_[0]); header[0].command = 7; header[0].size = 1; header[1].command = 8; @@ -224,10 +221,10 @@ TEST_F(GPUProcessorTest, UnrecoverableParseErrorsRaiseTheErrorStatus) { .WillOnce(Return(2)); EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0])) - .WillOnce(Return(gpu::parse_error::kParseInvalidSize)); + .WillOnce(Return(parse_error::kParseInvalidSize)); EXPECT_CALL(*command_buffer_, - SetParseError(gpu::parse_error::kParseInvalidSize)); + SetParseError(parse_error::kParseInvalidSize)); EXPECT_CALL(*command_buffer_, RaiseErrorStatus()); @@ -246,27 +243,20 @@ TEST_F(GPUProcessorTest, ProcessCommandsDoesNothingAfterUnrecoverableError) { TEST_F(GPUProcessorTest, CanGetAddressOfSharedMemory) { EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7)) - .WillOnce(Return(shared_memory_.get())); + .WillOnce(Return(shared_memory_buffer_)); - EXPECT_EQ(&buffer_[0], processor_->GetSharedMemoryAddress(7)); + EXPECT_EQ(&buffer_[0], processor_->GetSharedMemoryBuffer(7).ptr); } ACTION_P2(SetPointee, address, value) { *address = value; } -TEST_F(GPUProcessorTest, GetAddressOfSharedMemoryMapsMemoryIfUnmapped) { - EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7)) - .WillOnce(Return(shared_memory_.get())); - - EXPECT_EQ(&buffer_[0], processor_->GetSharedMemoryAddress(7)); -} - TEST_F(GPUProcessorTest, CanGetSizeOfSharedMemory) { EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7)) - .WillOnce(Return(shared_memory_.get())); + .WillOnce(Return(shared_memory_buffer_)); - EXPECT_EQ(kRingBufferSize, processor_->GetSharedMemorySize(7)); + EXPECT_EQ(kRingBufferSize, processor_->GetSharedMemoryBuffer(7).size); } TEST_F(GPUProcessorTest, SetTokenForwardsToCommandBuffer) { diff --git a/gpu/command_buffer/service/gpu_processor_win.cc b/gpu/command_buffer/service/gpu_processor_win.cc index c08e102..6a05845 100644 --- a/gpu/command_buffer/service/gpu_processor_win.cc +++ b/gpu/command_buffer/service/gpu_processor_win.cc @@ -37,19 +37,17 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle handle) { return false; // Map the ring buffer and create the parser. - ::base::SharedMemory* ring_buffer = command_buffer_->GetRingBuffer(); - if (ring_buffer) { - size_t size = ring_buffer->max_size(); - if (!ring_buffer->Map(size)) { - return false; - } - - void* ptr = ring_buffer->memory(); - parser_.reset(new gpu::CommandParser(ptr, size, 0, size, 0, - decoder_.get())); + Buffer ring_buffer = command_buffer_->GetRingBuffer(); + if (ring_buffer.ptr) { + parser_.reset(new CommandParser(ring_buffer.ptr, + ring_buffer.size, + 0, + ring_buffer.size, + 0, + decoder_.get())); } else { - parser_.reset(new gpu::CommandParser(NULL, 0, 0, 0, 0, - decoder_.get())); + parser_.reset(new CommandParser(NULL, 0, 0, 0, 0, + decoder_.get())); } // Initialize GAPI immediately if the window handle is valid. @@ -64,17 +62,4 @@ void GPUProcessor::Destroy() { decoder_->set_hwnd(NULL); } } - -bool GPUProcessor::SetWindow(gfx::PluginWindowHandle handle, - int width, - int height) { - if (handle == NULL) { - // Destroy GAPI when the window handle becomes invalid. - Destroy(); - return true; - } else { - return Initialize(handle); - } -} - } // namespace gpu diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index 5a5c113..d4de4c5 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp @@ -85,6 +85,7 @@ ], 'sources': [ 'command_buffer/common/bitfield_helpers.h', + 'command_buffer/common/buffer.h', 'command_buffer/common/cmd_buffer_common.h', 'command_buffer/common/cmd_buffer_common.cc', 'command_buffer/common/command_buffer.h', @@ -278,7 +279,7 @@ }, { 'target_name': 'gpu_plugin', - 'type': '<(library)', + 'type': 'static_library', 'dependencies': [ '../base/base.gyp:base', 'command_buffer_service', @@ -312,24 +313,40 @@ ], }, { - 'target_name': 'gles2_demo', - 'type': 'executable', + 'target_name': 'gles2_demo_lib', + 'type': 'static_library', 'dependencies': [ 'command_buffer_client', - 'command_buffer_service', 'gles2_lib', 'gles2_c_lib', - 'gpu_plugin', ], 'sources': [ - 'command_buffer/client/gles2_demo.cc', 'command_buffer/client/gles2_demo_c.h', 'command_buffer/client/gles2_demo_c.c', 'command_buffer/client/gles2_demo_cc.h', 'command_buffer/client/gles2_demo_cc.cc', ], }, - ] + ], + 'conditions': [ + ['OS == "win"', + { + 'targets': [ + { + 'target_name': 'gles2_demo', + 'type': 'executable', + 'dependencies': [ + 'command_buffer_service', + 'gles2_demo_lib', + ], + 'sources': [ + 'command_buffer/client/gles2_demo.cc', + ], + }, + ], + }, + ], + ], } # Local Variables: diff --git a/gpu/gpu_plugin/gpu_plugin.cc b/gpu/gpu_plugin/gpu_plugin.cc index e43caf1..10df734 100644 --- a/gpu/gpu_plugin/gpu_plugin.cc +++ b/gpu/gpu_plugin/gpu_plugin.cc @@ -47,7 +47,7 @@ NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) { } } -NPError NP_GetEntryPoints(NPPluginFuncs* funcs) { +NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* funcs) { funcs->newp = NPP_New; funcs->destroy = NPP_Destroy; funcs->setwindow = NPP_SetWindow; @@ -61,7 +61,7 @@ NPError NP_GetEntryPoints(NPPluginFuncs* funcs) { NPError API_CALL NP_Initialize(NPNetscapeFuncs *browser_funcs, NPPluginFuncs* plugin_funcs) { #else -NPError NP_Initialize(NPNetscapeFuncs *browser_funcs) { +NPError API_CALL NP_Initialize(NPNetscapeFuncs *browser_funcs) { #endif if (!browser_funcs) return NPERR_INVALID_FUNCTABLE_ERROR; @@ -73,7 +73,7 @@ NPError NP_Initialize(NPNetscapeFuncs *browser_funcs) { return NPERR_NO_ERROR; } -NPError NP_Shutdown() { +NPError API_CALL NP_Shutdown() { return NPERR_NO_ERROR; } } // namespace gpu_plugin diff --git a/gpu/gpu_plugin/gpu_plugin.h b/gpu/gpu_plugin/gpu_plugin.h index a667872..b6bfc89 100644 --- a/gpu/gpu_plugin/gpu_plugin.h +++ b/gpu/gpu_plugin/gpu_plugin.h @@ -15,16 +15,16 @@ namespace gpu_plugin { // Declarations of NPAPI plugin entry points. -NPError NP_GetEntryPoints(NPPluginFuncs* funcs); +NPError API_CALL NP_GetEntryPoints(NPPluginFuncs* funcs); #if defined(OS_LINUX) -NPError NP_Initialize(NPNetscapeFuncs *browser_funcs, +NPError API_CALL NP_Initialize(NPNetscapeFuncs *browser_funcs, NPPluginFuncs* plugin_funcs); #else -NPError NP_Initialize(NPNetscapeFuncs* browser_funcs); +NPError API_CALL NP_Initialize(NPNetscapeFuncs* browser_funcs); #endif -NPError NP_Shutdown(); +NPError API_CALL NP_Shutdown(); } // namespace gpu_plugin diff --git a/third_party/npapi/bindings/npapi_extensions.h b/third_party/npapi/bindings/npapi_extensions.h index 67c8ca9..ac57613 100644 --- a/third_party/npapi/bindings/npapi_extensions.h +++ b/third_party/npapi/bindings/npapi_extensions.h @@ -21,6 +21,12 @@ typedef void NPUserData; /* unique id for each device interface */ typedef int32 NPDeviceID; + +typedef struct _NPDeviceBuffer { + void* ptr; + size_t size; +} NPDeviceBuffer; + /* completion callback for flush device */ typedef void (*NPDeviceFlushContextCallbackPtr)( NPP instace, @@ -67,6 +73,25 @@ typedef NPError (*NPDeviceFlushContextPtr)( typedef NPError (*NPDeviceDestroyContextPtr)( NPP instance, NPDeviceContext* context); +/* Create a buffer associated with a particular context. The usage of the */ +/* buffer is device specific. The lifetime of the buffer is scoped with the */ +/* lifetime of the context. */ +typedef NPError (*NPDeviceCreateBufferPtr)( + NPP instance, + NPDeviceContext* context, + size_t size, + int32* id); +/* Destroy a buffer associated with a particular context. */ +typedef NPError (*NPDeviceDestroyBufferPtr)( + NPP instance, + NPDeviceContext* context, + int32 id); +/* Map a buffer id to its address. */ +typedef NPError (*NPDeviceMapBufferPtr)( + NPP instance, + NPDeviceContext* context, + int32 id, + NPDeviceBuffer* buffer); /* forward decl typdef structs */ typedef struct NPDevice NPDevice; @@ -81,6 +106,9 @@ struct NPDevice { NPDeviceGetStateContextPtr getStateContext; NPDeviceFlushContextPtr flushContext; NPDeviceDestroyContextPtr destroyContext; + NPDeviceCreateBufferPtr createBuffer; + NPDeviceDestroyBufferPtr destroyBuffer; + NPDeviceMapBufferPtr mapBuffer; }; /* returns NULL if deviceID unavailable / unrecognized */ @@ -225,13 +253,36 @@ typedef struct _NPDeviceContext2D #define NPPepper3DDevice 2 typedef struct _NPDeviceContext3DConfig { + int32 commandBufferEntries; } NPDeviceContext3DConfig; +typedef enum { + // The offset the command buffer service has read to. + NPDeviceContext3DState_GetOffset, + // The offset the plugin instance has written to. + NPDeviceContext3DState_PutOffset, + // The last token processed by the command buffer service. + NPDeviceContext3DState_Token, + // The most recent parse error. Getting this value resets the parse error + // if it recoverable. + NPDeviceContext3DState_ParseError, + // Wether the command buffer has encountered an unrecoverable error. + NPDeviceContext3DState_ErrorStatus, +} NPDeviceContext3DState; + typedef struct _NPDeviceContext3D { void* reserved; - void* buffer; - int32 bufferLength; + + // Buffer in which commands are stored. + void* commandBuffer; + int32 commandBufferEntries; + + // Offset in command buffer reader has reached. Synchronized on flush. + int32 getOffset; + + // Offset in command buffer writer has reached. Synchronized on flush. + int32 putOffset; } NPDeviceContext3D; #endif /* _NP_EXTENSIONS_H_ */ diff --git a/webkit/glue/plugins/npapi_extension_thunk.cc b/webkit/glue/plugins/npapi_extension_thunk.cc index e07bff2..eee6c80 100644 --- a/webkit/glue/plugins/npapi_extension_thunk.cc +++ b/webkit/glue/plugins/npapi_extension_thunk.cc @@ -114,6 +114,26 @@ static NPError Device2DDestroyContext(NPP id, return NPERR_GENERIC_ERROR; } +static NPError Device2DCreateBuffer(NPP id, + NPDeviceContext* context, + size_t size, + int32* buffer_id) { + return NPERR_GENERIC_ERROR; +} + +static NPError Device2DDestroyBuffer(NPP id, + NPDeviceContext* context, + int32 buffer_id) { + return NPERR_GENERIC_ERROR; +} + +static NPError Device2DMapBuffer(NPP id, + NPDeviceContext* context, + int32 buffer_id, + NPDeviceBuffer* buffer) { + return NPERR_GENERIC_ERROR; +} + // 3D device API --------------------------------------------------------------- static NPError Device3DQueryCapability(NPP id, int32 capability, int32* value) { @@ -196,6 +216,41 @@ static NPError Device3DDestroyContext(NPP id, return NPERR_GENERIC_ERROR; } +static NPError Device3DCreateBuffer(NPP id, + NPDeviceContext* context, + size_t size, + int32* buffer_id) { + scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DCreateBuffer( + static_cast<NPDeviceContext3D*>(context), size, buffer_id); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DDestroyBuffer(NPP id, + NPDeviceContext* context, + int32 buffer_id) { + scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DDestroyBuffer( + static_cast<NPDeviceContext3D*>(context), buffer_id); + } + return NPERR_GENERIC_ERROR; +} + +static NPError Device3DMapBuffer(NPP id, + NPDeviceContext* context, + int32 buffer_id, + NPDeviceBuffer* buffer) { + scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id); + if (plugin) { + return plugin->webplugin()->delegate()->Device3DMapBuffer( + static_cast<NPDeviceContext3D*>(context), buffer_id, buffer); + } + return NPERR_GENERIC_ERROR; +} + // ----------------------------------------------------------------------------- static NPDevice* AcquireDevice(NPP id, NPDeviceID device_id) { @@ -207,6 +262,9 @@ static NPDevice* AcquireDevice(NPP id, NPDeviceID device_id) { Device2DGetStateContext, Device2DFlushContext, Device2DDestroyContext, + Device2DCreateBuffer, + Device2DDestroyBuffer, + Device2DMapBuffer, }; static NPDevice device_3d = { Device3DQueryCapability, @@ -216,6 +274,9 @@ static NPDevice* AcquireDevice(NPP id, NPDeviceID device_id) { Device3DGetStateContext, Device3DFlushContext, Device3DDestroyContext, + Device3DCreateBuffer, + Device3DDestroyBuffer, + Device3DMapBuffer, }; switch (device_id) { diff --git a/webkit/glue/plugins/plugin_constants_win.h b/webkit/glue/plugins/plugin_constants_win.h index b708706..9913e5d 100644 --- a/webkit/glue/plugins/plugin_constants_win.h +++ b/webkit/glue/plugins/plugin_constants_win.h @@ -36,4 +36,6 @@ #define kJavaPlugin1 L"npjp2.dll" #define kJavaPlugin2 L"npdeploytk.dll" +#define kGPUPluginMimeType "application/vnd.google.chrome.gpu-plugin" + #endif // WEBKIT_GLUE_PLUGIN_PLUGIN_LIST_H_ diff --git a/webkit/glue/plugins/plugin_list.cc b/webkit/glue/plugins/plugin_list.cc index 2109951..ec4a80b 100644 --- a/webkit/glue/plugins/plugin_list.cc +++ b/webkit/glue/plugins/plugin_list.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. diff --git a/webkit/glue/plugins/plugin_list.h b/webkit/glue/plugins/plugin_list.h index 822ac05..ec82fd0 100644 --- a/webkit/glue/plugins/plugin_list.h +++ b/webkit/glue/plugins/plugin_list.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. diff --git a/webkit/glue/plugins/plugin_list_win.cc b/webkit/glue/plugins/plugin_list_win.cc index b762a8f..25a3be4 100644 --- a/webkit/glue/plugins/plugin_list_win.cc +++ b/webkit/glue/plugins/plugin_list_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// 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. diff --git a/webkit/glue/plugins/webplugin_3d_device_delegate.h b/webkit/glue/plugins/webplugin_3d_device_delegate.h index 78dbe0e..42dc300 100644 --- a/webkit/glue/plugins/webplugin_3d_device_delegate.h +++ b/webkit/glue/plugins/webplugin_3d_device_delegate.h @@ -46,6 +46,20 @@ class WebPlugin3DDeviceDelegate { virtual NPError Device3DDestroyContext(NPDeviceContext3D* context) { return NPERR_GENERIC_ERROR; } + virtual NPError Device3DCreateBuffer(NPDeviceContext3D* context, + size_t size, + int32* id) { + return NPERR_GENERIC_ERROR; + } + virtual NPError Device3DDestroyBuffer(NPDeviceContext3D* context, + int32 id) { + return NPERR_GENERIC_ERROR; + } + virtual NPError Device3DMapBuffer(NPDeviceContext3D* context, + int32 id, + NPDeviceBuffer* buffer) { + return NPERR_GENERIC_ERROR; + } protected: WebPlugin3DDeviceDelegate() {} diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc index 2cc4962..8c1ffa9 100644 --- a/webkit/glue/webplugin_impl.cc +++ b/webkit/glue/webplugin_impl.cc @@ -74,7 +74,7 @@ namespace { // specified in the response header. class MultiPartResponseClient : public WebURLLoaderClient { public: - MultiPartResponseClient(WebPluginResourceClient* resource_client) + explicit MultiPartResponseClient(WebPluginResourceClient* resource_client) : resource_client_(resource_client) { Clear(); } @@ -398,7 +398,7 @@ WebPluginImpl::~WebPluginImpl() { void WebPluginImpl::SetWindow(gfx::PluginWindowHandle window) { if (window) { - DCHECK(!windowless_); // Make sure not called twice. + DCHECK(!windowless_); window_ = window; if (page_delegate_) { // Tell the view delegate that the plugin window was created, so that it diff --git a/webkit/tools/pepper_test_plugin/DEPS b/webkit/tools/pepper_test_plugin/DEPS new file mode 100644 index 0000000..03c7a2d --- /dev/null +++ b/webkit/tools/pepper_test_plugin/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+gpu/command_buffer", +] diff --git a/webkit/tools/pepper_test_plugin/command_buffer_pepper.cc b/webkit/tools/pepper_test_plugin/command_buffer_pepper.cc new file mode 100644 index 0000000..d7fbf7a --- /dev/null +++ b/webkit/tools/pepper_test_plugin/command_buffer_pepper.cc @@ -0,0 +1,180 @@ +// 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 "webkit/tools/pepper_test_plugin/command_buffer_pepper.h" + +using base::SharedMemory; +using gpu::Buffer; + +CommandBufferPepper::CommandBufferPepper(NPP npp, NPNetscapeFuncs* browser) + : npp_(npp), + browser_(browser), + extensions_(NULL), + device_(NULL) { +} + +CommandBufferPepper::~CommandBufferPepper() { + if (device_) { + device_->destroyContext(npp_, &context_); + device_ = NULL; + } +} + +bool CommandBufferPepper::Initialize(int32 size) { + if (device_) + return false; + + // Get the pepper extensions. + browser_->getvalue(npp_, + NPNVPepperExtensions, + reinterpret_cast<void*>(&extensions_)); + CHECK(extensions_); + + // Acquire a 3D device. + device_ = extensions_->acquireDevice(npp_, NPPepper3DDevice); + if (device_) { + NPDeviceContext3DConfig config; + config.commandBufferEntries = size; + if (NPERR_NO_ERROR == device_->initializeContext(npp_, + &config, + &context_)) { + return true; + } + } + + return false; +} + +Buffer CommandBufferPepper::GetRingBuffer() { + Buffer buffer; + buffer.ptr = context_.commandBuffer; + buffer.size = context_.commandBufferEntries * sizeof(int32); + return buffer; +} + +int32 CommandBufferPepper::GetSize() { + return context_.commandBufferEntries; +} + +int32 CommandBufferPepper::SyncOffsets(int32 put_offset) { + context_.putOffset = put_offset; + if (NPERR_NO_ERROR != device_->flushContext(npp_, &context_, NULL, NULL)) + return -1; + + return context_.getOffset; +} + +int32 CommandBufferPepper::GetGetOffset() { + int32 value; + if (NPERR_NO_ERROR != device_->getStateContext( + npp_, + &context_, + NPDeviceContext3DState_GetOffset, + &value)) { + return -1; + } + + return value; +} + +void CommandBufferPepper::SetGetOffset(int32 get_offset) { + // Not implemented by proxy. + NOTREACHED(); +} + +int32 CommandBufferPepper::GetPutOffset() { + int32 value; + if (NPERR_NO_ERROR != device_->getStateContext( + npp_, + &context_, + NPDeviceContext3DState_PutOffset, + &value)) { + return -1; + } + + return value; +} + +void CommandBufferPepper::SetPutOffsetChangeCallback( + Callback0::Type* callback) { + // Not implemented by proxy. + NOTREACHED(); +} + +int32 CommandBufferPepper::CreateTransferBuffer(size_t size) { + int32 id; + if (NPERR_NO_ERROR != device_->createBuffer(npp_, &context_, size, &id)) + return -1; + + return id; +} + +void CommandBufferPepper::DestroyTransferBuffer(int32 id) { + device_->destroyBuffer(npp_, &context_, id); +} + +Buffer CommandBufferPepper::GetTransferBuffer(int32 id) { + NPDeviceBuffer np_buffer; + if (NPERR_NO_ERROR != device_->mapBuffer(npp_, &context_, id, &np_buffer)) + return Buffer(); + + Buffer buffer; + buffer.ptr = np_buffer.ptr; + buffer.size = np_buffer.size; + return buffer; +} + +int32 CommandBufferPepper::GetToken() { + int32 value; + if (NPERR_NO_ERROR != device_->getStateContext( + npp_, + &context_, + NPDeviceContext3DState_Token, + &value)) { + return -1; + } + + return value; +} + +void CommandBufferPepper::SetToken(int32 token) { + // Not implemented by proxy. + NOTREACHED(); +} + +int32 CommandBufferPepper::ResetParseError() { + int32 value; + if (NPERR_NO_ERROR != device_->getStateContext( + npp_, + &context_, + NPDeviceContext3DState_ParseError, + &value)) { + return -1; + } + + return value; +} + +void CommandBufferPepper::SetParseError(int32 parse_error) { + // Not implemented by proxy. + NOTREACHED(); +} + +bool CommandBufferPepper::GetErrorStatus() { + int32 value; + if (NPERR_NO_ERROR != device_->getStateContext( + npp_, + &context_, + NPDeviceContext3DState_ErrorStatus, + &value)) { + return value != 0; + } + + return true; +} + +void CommandBufferPepper::RaiseErrorStatus() { + // Not implemented by proxy. + NOTREACHED(); +} diff --git a/webkit/tools/pepper_test_plugin/command_buffer_pepper.h b/webkit/tools/pepper_test_plugin/command_buffer_pepper.h new file mode 100644 index 0000000..5fc2486 --- /dev/null +++ b/webkit/tools/pepper_test_plugin/command_buffer_pepper.h @@ -0,0 +1,52 @@ +// 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 WEBKIT_TOOLS_PEPPER_TEST_PLUGIN_COMMAND_BUFFER_PEPPER_H_ +#define WEBKIT_TOOLS_PEPPER_TEST_PLUGIN_COMMAND_BUFFER_PEPPER_H_ + +#include "gpu/command_buffer/common/command_buffer.h" +#include "third_party/npapi/bindings/npapi.h" +#include "third_party/npapi/bindings/npruntime.h" +#include "webkit/glue/plugins/nphostapi.h" + +// A CommandBuffer proxy implementation that uses the Pepper API to access +// the command buffer. +// TODO(apatrick): move this into a library that can be used by any pepper +// plugin. + +class CommandBufferPepper : public gpu::CommandBuffer { + public: + CommandBufferPepper(NPP npp, NPNetscapeFuncs* browser); + virtual ~CommandBufferPepper(); + + // CommandBuffer implementation. + virtual bool Initialize(int32 size); + virtual gpu::Buffer GetRingBuffer(); + virtual int32 GetSize(); + virtual int32 SyncOffsets(int32 put_offset); + virtual int32 GetGetOffset(); + virtual void SetGetOffset(int32 get_offset); + virtual int32 GetPutOffset(); + virtual void SetPutOffsetChangeCallback(Callback0::Type* callback); + virtual int32 CreateTransferBuffer(size_t size); + virtual void DestroyTransferBuffer(int32 id); + virtual gpu::Buffer GetTransferBuffer(int32 handle); + virtual int32 GetToken(); + virtual void SetToken(int32 token); + virtual int32 ResetParseError(); + virtual void SetParseError(int32 parse_error); + virtual bool GetErrorStatus(); + virtual void RaiseErrorStatus(); + + private: + NPP npp_; + NPNetscapeFuncs* browser_; + NPExtensions* extensions_; + NPDevice* device_; + NPDeviceContext3D context_; +}; + +#endif // WEBKIT_TOOLS_PEPPER_TEST_PLUGIN_COMMAND_BUFFER_PEPPER_H_ + + diff --git a/webkit/tools/pepper_test_plugin/main.cc b/webkit/tools/pepper_test_plugin/main.cc index 1b7da69..ef9a64b 100644 --- a/webkit/tools/pepper_test_plugin/main.cc +++ b/webkit/tools/pepper_test_plugin/main.cc @@ -171,6 +171,8 @@ NPError NPP_New(NPMIMEType pluginType, browser->createobject(instance, PluginObject::GetPluginClass())); instance->pdata = obj; event_handler = new EventHandler(instance); + + obj->New(pluginType, argc, argn, argv); } return NPERR_NO_ERROR; diff --git a/webkit/tools/pepper_test_plugin/pepper_test_plugin.gyp b/webkit/tools/pepper_test_plugin/pepper_test_plugin.gyp index 168fe53..aa3908a 100644 --- a/webkit/tools/pepper_test_plugin/pepper_test_plugin.gyp +++ b/webkit/tools/pepper_test_plugin/pepper_test_plugin.gyp @@ -16,6 +16,9 @@ ['OS=="win"', { 'product_name': 'pepper_test_plugin', 'msvs_guid': 'EE00E36E-9E8C-4DFB-925E-FBE32CEDB91A', + 'dependencies': [ + '../../../gpu/gpu.gyp:gles2_demo_lib', + ], 'sources': [ 'pepper_test_plugin.def', 'pepper_test_plugin.rc', @@ -23,6 +26,8 @@ }] ], 'sources': [ + 'command_buffer_pepper.cc', + 'command_buffer_pepper.h', 'main.cc', 'plugin_object.cc', 'plugin_object.h', @@ -32,11 +37,11 @@ 'event_handler.h' ], 'run_as': { - 'working_directory': '.', 'action': [ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)chrome<(EXECUTABLE_SUFFIX)', '--no-sandbox', '--internal-pepper', + '--enable-gpu-plugin', '--load-plugin=$(TargetPath)', 'file://$(ProjectDir)test_page.html', ], diff --git a/webkit/tools/pepper_test_plugin/plugin_object.cc b/webkit/tools/pepper_test_plugin/plugin_object.cc index d7eaa09..59212ac 100644 --- a/webkit/tools/pepper_test_plugin/plugin_object.cc +++ b/webkit/tools/pepper_test_plugin/plugin_object.cc @@ -29,6 +29,8 @@ #include <string> #include "base/logging.h" +#include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/command_buffer/client/gles2_demo_cc.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/effects/SkGradientShader.h" @@ -247,13 +249,6 @@ PluginObject::PluginObject(NPP npp) : npp_(npp), test_object_(browser->createobject(npp, GetTestClass())), device2d_(NULL) { - if (!extensions) { - browser->getvalue(npp_, NPNVPepperExtensions, - reinterpret_cast<void*>(&extensions)); - CHECK(extensions); - } - device2d_ = extensions->acquireDevice(npp, NPPepper2DDevice); - CHECK(device2d_); } PluginObject::~PluginObject() { @@ -266,24 +261,105 @@ NPClass* PluginObject::GetPluginClass() { return &plugin_class; } +namespace { +void Draw3DCallback(void* data) { + static_cast<PluginObject*>(data)->Draw3D(); +} +} + +void PluginObject::New(NPMIMEType pluginType, + int16 argc, + char* argn[], + char* argv[]) { + // Default to 2D rendering. + dimensions_ = 2; + + for (int i = 0; i < argc; ++i) { + if (strcmp(argn[i], "dimensions") == 0) + dimensions_ = atoi(argv[i]); + } + + if (!extensions) { + browser->getvalue(npp_, NPNVPepperExtensions, + reinterpret_cast<void*>(&extensions)); + CHECK(extensions); + } + device2d_ = extensions->acquireDevice(npp_, NPPepper2DDevice); + CHECK(device2d_); +} + void PluginObject::SetWindow(const NPWindow& window) { - size_.set_width(window.width); - size_.set_height(window.height); + if (dimensions_ == 2) { + size_.set_width(window.width); + size_.set_height(window.height); + + NPDeviceContext2DConfig config; + NPDeviceContext2D context; + device2d_->initializeContext(npp_, &config, &context); + + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, window.width, window.height); + bitmap.setPixels(context.region); + + SkCanvas canvas(bitmap); + DrawSampleBitmap(canvas, window.width, window.height); + + // TODO(brettw) figure out why this cast is necessary, the functions seem to + // match. Could be a calling convention mismatch? + NPDeviceFlushContextCallbackPtr callback = + reinterpret_cast<NPDeviceFlushContextCallbackPtr>(&FlushCallback); + device2d_->flushContext(npp_, &context, callback, NULL); + } else { + if (!command_buffer_.get()) { + if (!InitializeCommandBuffer()) + return; + } + + gles2_implementation_->Viewport(0, 0, window.width, window.height); + + // Schedule the first call to Draw. + browser->pluginthreadasynccall(npp_, Draw3DCallback, this); + } +} + +void PluginObject::Draw3D() { + // Render some stuff. + gles2::g_gl_impl = gles2_implementation_.get(); + GLFromCPPTestFunction(); + gles2::GetGLContext()->SwapBuffers(); + helper_->Flush(); + gles2::g_gl_impl = NULL; + + // Schedule another call to Draw. + browser->pluginthreadasynccall(npp_, Draw3DCallback, this); +} - NPDeviceContext2DConfig config; - NPDeviceContext2D context; - device2d_->initializeContext(npp_, &config, &context); +bool PluginObject::InitializeCommandBuffer() { + const static int32 kCommandBufferSize = 512 * 1024; + command_buffer_.reset(new CommandBufferPepper(npp_, browser)); + if (command_buffer_->Initialize(kCommandBufferSize)) { + helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_.get())); + if (helper_->Initialize()) { + + const int32 kTransferBufferSize = 512 * 1024; + int32 transfer_buffer_id = + command_buffer_->CreateTransferBuffer(kTransferBufferSize); + gpu::Buffer transfer_buffer = + command_buffer_->GetTransferBuffer(transfer_buffer_id); + if (transfer_buffer.ptr) { + gles2_implementation_.reset(new gpu::gles2::GLES2Implementation( + helper_.get(), + transfer_buffer.size, + transfer_buffer.ptr, + transfer_buffer_id)); + return true; + } + } - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, window.width, window.height); - bitmap.setPixels(context.region); + helper_.reset(); + } - SkCanvas canvas(bitmap); - DrawSampleBitmap(canvas, window.width, window.height); + command_buffer_.reset(); - // TODO(brettw) figure out why this cast is necessary, the functions seem to - // match. Could be a calling convention mismatch? - NPDeviceFlushContextCallbackPtr callback = - reinterpret_cast<NPDeviceFlushContextCallbackPtr>(&FlushCallback); - device2d_->flushContext(npp_, &context, callback, NULL); + return false; } diff --git a/webkit/tools/pepper_test_plugin/plugin_object.h b/webkit/tools/pepper_test_plugin/plugin_object.h index 1dcbb80..4dcff15 100644 --- a/webkit/tools/pepper_test_plugin/plugin_object.h +++ b/webkit/tools/pepper_test_plugin/plugin_object.h @@ -28,13 +28,16 @@ #include "base/basictypes.h" #include "base/gfx/size.h" +#include "base/scoped_ptr.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "webkit/tools/pepper_test_plugin/command_buffer_pepper.h" #include "webkit/glue/plugins/nphostapi.h" extern NPNetscapeFuncs* browser; class PluginObject { public: - PluginObject(NPP npp); + explicit PluginObject(NPP npp); ~PluginObject(); static NPClass* GetPluginClass(); @@ -42,15 +45,26 @@ class PluginObject { NPObject* header() { return &header_; } NPP npp() const { return npp_; } + void New(NPMIMEType pluginType, int16 argc, char* argn[], char* argv[]); void SetWindow(const NPWindow& window); + void Draw3D(); private: + bool InitializeCommandBuffer(); + NPObject header_; NPP npp_; NPObject* test_object_; + int dimensions_; NPDevice* device2d_; + // TODO(apatrick): this destruction order causes the plugin to crash on + // shutdown. + scoped_ptr<CommandBufferPepper> command_buffer_; + scoped_ptr<gpu::gles2::GLES2Implementation> gles2_implementation_; + scoped_ptr<gpu::gles2::GLES2CmdHelper> helper_; + gfx::Size size_; DISALLOW_COPY_AND_ASSIGN(PluginObject); diff --git a/webkit/tools/pepper_test_plugin/test_page.html b/webkit/tools/pepper_test_plugin/test_page.html index c25dbd2..f9bf2b8 100644 --- a/webkit/tools/pepper_test_plugin/test_page.html +++ b/webkit/tools/pepper_test_plugin/test_page.html @@ -25,7 +25,7 @@ This page embeds a file declared as the pepper test plugins MIME type so that it <table> <tr> <td valign="top" width="50%"> -<object id="plugin" type="pepper-application/x-pepper-test-plugin" width="400" height="400" /> +<object id="plugin" type="pepper-application/x-pepper-test-plugin" width="400" height="400" dimensions="2" /> </td> <td valign="top" style="background-color:Silver" width="50%"> <div id="event_text_box" style="width:400px; height:400px; overflow:auto"> diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp index adc6687..2d95286 100644 --- a/webkit/webkit.gyp +++ b/webkit/webkit.gyp @@ -452,6 +452,7 @@ ], 'dependencies': [ '../build/win/system.gyp:cygwin', + '../gpu/gpu.gyp:gpu_plugin', 'default_plugin/default_plugin.gyp:default_plugin', ], 'sources!': [ |