diff options
-rw-r--r-- | chrome/app/chrome_main.cc | 6 | ||||
-rw-r--r-- | chrome/chrome.gyp | 10 | ||||
-rw-r--r-- | chrome/chrome_common.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/common/gpu_plugin.cc | 36 | ||||
-rw-r--r-- | chrome/common/gpu_plugin.h | 16 | ||||
-rw-r--r-- | chrome/common/plugin_messages_internal.h | 5 | ||||
-rw-r--r-- | chrome/plugin/command_buffer_stub.cc | 195 | ||||
-rw-r--r-- | chrome/plugin/command_buffer_stub.h | 84 | ||||
-rw-r--r-- | chrome/plugin/command_buffer_stub_win.cc | 73 | ||||
-rw-r--r-- | chrome/plugin/plugin_main.cc | 2 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.cc | 38 | ||||
-rw-r--r-- | chrome/plugin/webplugin_delegate_stub.h | 9 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.cc | 455 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_pepper.h | 37 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.cc | 31 | ||||
-rw-r--r-- | chrome/renderer/webplugin_delegate_proxy.h | 4 | ||||
-rw-r--r-- | chrome/test/ui/pepper_uitest.cc | 47 | ||||
-rw-r--r-- | content/browser/plugin_process_host.cc | 1 | ||||
-rw-r--r-- | content/browser/plugin_service.cc | 3 | ||||
-rw-r--r-- | gpu/gpu.gyp | 20 | ||||
-rw-r--r-- | webkit/glue/webkit_glue.gypi | 5 |
22 files changed, 1061 insertions, 19 deletions
diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc index b8f5a15..71bb4c2 100644 --- a/chrome/app/chrome_main.cc +++ b/chrome/app/chrome_main.cc @@ -517,6 +517,12 @@ int ChromeMain(int argc, char** argv) { return 1; #endif + if (command_line.HasSwitch(switches::kEnableNaCl)) { + // NaCl currently requires two flags to run + CommandLine* singleton_command_line = CommandLine::ForCurrentProcess(); + singleton_command_line->AppendSwitch(switches::kEnableGPUPlugin); + } + base::ProcessId browser_pid = base::GetCurrentProcId(); if (SubprocessIsBrowserChild(process_type)) { #if defined(OS_WIN) || defined(OS_MACOSX) diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index f7a2c0f..49b2219 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -601,6 +601,16 @@ '<(DEPTH)/third_party/wtl/include', ], }], + ['enable_gpu==1', { + 'dependencies': [ + '../gpu/gpu.gyp:command_buffer_service', + ], + 'sources': [ + 'plugin/command_buffer_stub.cc', + 'plugin/command_buffer_stub.h', + 'plugin/command_buffer_stub_win.cc', + ], + },], ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', { 'dependencies': [ '../build/linux/system.gyp:gtk', diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 8b678d1..3fad755 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -303,6 +303,8 @@ 'common/font_loader_mac.h', 'common/font_loader_mac.mm', 'common/gears_api.h', + 'common/gpu_plugin.cc', + 'common/gpu_plugin.h', 'common/important_file_writer.cc', 'common/important_file_writer.h', 'common/json_pref_store.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 31b3f76..83b46df 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -591,6 +591,7 @@ 'test/ui/named_interface_uitest.cc', 'test/ui/npapi_uitest.cc', 'test/ui/omnibox_uitest.cc', + 'test/ui/pepper_uitest.cc', 'test/ui/ppapi_uitest.cc', 'test/ui/sandbox_uitests.cc', 'test/ui/sunspider_uitest.cc', diff --git a/chrome/common/gpu_plugin.cc b/chrome/common/gpu_plugin.cc new file mode 100644 index 0000000..fd4c680 --- /dev/null +++ b/chrome/common/gpu_plugin.cc @@ -0,0 +1,36 @@ +// 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 "chrome/common/gpu_plugin.h" + +#include "base/command_line.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "chrome/common/chrome_switches.h" +#include "gpu/gpu_plugin/gpu_plugin.h" +#include "webkit/plugins/npapi/plugin_list.h" + +namespace chrome { + +void RegisterInternalGPUPlugin() { +#if defined(ENABLE_GPU) + const webkit::npapi::PluginEntryPoints entry_points = { +#if !defined(OS_POSIX) || defined(OS_MACOSX) + gpu_plugin::NP_GetEntryPoints, +#endif + gpu_plugin::NP_Initialize, + gpu_plugin::NP_Shutdown + }; + + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableGPUPlugin)) + webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin( + FilePath(FILE_PATH_LITERAL("gpu-plugin")), + "GPU Plug-in", + "GPU Rendering Plug-in", + "application/vnd.google.chrome.gpu-plugin", + entry_points); +#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..938cbc2e --- /dev/null +++ b/chrome/common/gpu_plugin.h @@ -0,0 +1,16 @@ +// 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_ +#pragma once + +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/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h index dec7a89..98ed543 100644 --- a/chrome/common/plugin_messages_internal.h +++ b/chrome/common/plugin_messages_internal.h @@ -285,6 +285,11 @@ IPC_MESSAGE_ROUTED2(PluginMsg_HTTPRangeRequestReply, unsigned long /* resource_id */, int /* range_request_id */) +IPC_SYNC_MESSAGE_ROUTED0_1(PluginMsg_CreateCommandBuffer, + int /* route_id */) + +IPC_MESSAGE_ROUTED0(PluginMsg_DestroyCommandBuffer) + IPC_MESSAGE_CONTROL1(PluginMsg_SignalModalDialogEvent, gfx::NativeViewId /* containing_window */) diff --git a/chrome/plugin/command_buffer_stub.cc b/chrome/plugin/command_buffer_stub.cc new file mode 100644 index 0000000..9aea1ee --- /dev/null +++ b/chrome/plugin/command_buffer_stub.cc @@ -0,0 +1,195 @@ +// 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 "chrome/plugin/command_buffer_stub.h" + +#include "base/callback.h" +#include "base/scoped_open_process.h" +#include "base/shared_memory.h" +#include "chrome/common/gpu_messages.h" +#include "chrome/common/plugin_messages.h" +#include "chrome/plugin/plugin_channel.h" + +using gpu::Buffer; + +CommandBufferStub::CommandBufferStub(PluginChannel* channel, + int plugin_host_route_id, + gfx::PluginWindowHandle window) + : channel_(channel), + plugin_host_route_id_(plugin_host_route_id), + window_(window) { + route_id_ = channel->GenerateRouteID(); + channel->AddRoute(route_id_, this, NULL); +} + +CommandBufferStub::~CommandBufferStub() { + Destroy(); + channel_->RemoveRoute(route_id_); +} + +bool CommandBufferStub::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(CommandBufferStub, message) + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Initialize, OnInitialize); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_GetState, OnGetState); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncGetState, OnAsyncGetState); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Flush, OnFlush); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncFlush, OnAsyncFlush); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateTransferBuffer, + OnCreateTransferBuffer); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyTransferBuffer, + OnDestroyTransferBuffer); + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_GetTransferBuffer, + OnGetTransferBuffer); +#if defined(OS_MACOSX) + IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetWindowSize, OnSetWindowSize); +#endif + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + DCHECK(handled); + return handled; +} + +void CommandBufferStub::OnChannelError() { + NOTREACHED() << "CommandBufferService::OnChannelError called"; +} + +bool CommandBufferStub::Send(IPC::Message* message) { + if (!channel_) { + delete message; + return false; + } + + return channel_->Send(message); +} + +void CommandBufferStub::NotifyRepaint() { + Send(new GpuCommandBufferMsg_NotifyRepaint(route_id_)); +} + +void CommandBufferStub::OnInitialize(base::SharedMemoryHandle ring_buffer, + int32 size, + bool* result) { + // TODO(apatrick): Pepper3D v1 is not used anymore. This function is never + // called. Delete the GPU plugin. + NOTREACHED(); + *result = false; +} + +void CommandBufferStub::OnGetState(gpu::CommandBuffer::State* state) { + *state = command_buffer_->GetState(); +} + +void CommandBufferStub::OnAsyncGetState() { + gpu::CommandBuffer::State state = command_buffer_->GetState(); + Send(new GpuCommandBufferMsg_UpdateState(route_id_, state)); +} + +void CommandBufferStub::OnFlush(int32 put_offset, + gpu::CommandBuffer::State* state) { + *state = command_buffer_->FlushSync(put_offset); +} + +void CommandBufferStub::OnAsyncFlush(int32 put_offset) { + gpu::CommandBuffer::State state = command_buffer_->FlushSync(put_offset); + Send(new GpuCommandBufferMsg_UpdateState(route_id_, state)); +} + +void CommandBufferStub::OnCreateTransferBuffer(int32 size, int32* id) { + *id = command_buffer_->CreateTransferBuffer(size); +} + +void CommandBufferStub::OnDestroyTransferBuffer(int32 id) { + command_buffer_->DestroyTransferBuffer(id); +} + +void CommandBufferStub::OnGetTransferBuffer( + int32 id, + base::SharedMemoryHandle* transfer_buffer, + uint32* size) { + *transfer_buffer = base::SharedMemoryHandle(); + *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)) + return; + + Buffer buffer = command_buffer_->GetTransferBuffer(id); + if (buffer.shared_memory) { + buffer.shared_memory->ShareToProcess(peer_handle, transfer_buffer); + *size = buffer.shared_memory->created_size(); + } + + base::CloseProcessHandle(peer_handle); +} + +void CommandBufferStub::Destroy() { + processor_.reset(); + command_buffer_.reset(); + + DestroyPlatformSpecific(); +} + +#if !defined(OS_WIN) +bool CommandBufferStub::InitializePlatformSpecific() { + return true; +} + +void CommandBufferStub::DestroyPlatformSpecific() { +} +#endif // defined(OS_WIN) + +#if defined(OS_MACOSX) +void CommandBufferStub::OnSetWindowSize(const gfx::Size& size) { + // Try using the IOSurface version first. + bool notify_repaint = false; + uint64 new_backing_store = processor_->SetWindowSizeForIOSurface(size); + if (new_backing_store) { + Send(new PluginHostMsg_AcceleratedSurfaceSetIOSurface( + plugin_host_route_id_, + window_, + size.width(), + size.height(), + new_backing_store)); + notify_repaint = true; + } else { + // If |new_backing_store| is 0, it might mean that the IOSurface APIs are + // not available. In this case, see if TransportDIBs are supported. + TransportDIB::Handle transport_dib = + processor_->SetWindowSizeForTransportDIB(size); + if (TransportDIB::is_valid(transport_dib)) { + Send(new PluginHostMsg_AcceleratedSurfaceSetTransportDIB( + plugin_host_route_id_, + window_, + size.width(), + size.height(), + transport_dib)); + notify_repaint = true; + } + } + if (notify_repaint) { + // Indicate to the client that at least one repaint is needed. + NotifyRepaint(); + } +} + +void CommandBufferStub::SwapBuffersCallback() { + Send(new PluginHostMsg_AcceleratedSurfaceBuffersSwapped( + plugin_host_route_id_, window_, processor_->GetSurfaceId())); +} + +void CommandBufferStub::AllocTransportDIB(const size_t size, + TransportDIB::Handle* dib_handle) { + Send(new PluginHostMsg_AllocTransportDIB(plugin_host_route_id_, + size, + dib_handle)); +} + +void CommandBufferStub::FreeTransportDIB(TransportDIB::Id dib_id) { + Send(new PluginHostMsg_FreeTransportDIB(plugin_host_route_id_, + dib_id)); +} +#endif diff --git a/chrome/plugin/command_buffer_stub.h b/chrome/plugin/command_buffer_stub.h new file mode 100644 index 0000000..a2667f1 --- /dev/null +++ b/chrome/plugin/command_buffer_stub.h @@ -0,0 +1,84 @@ +// 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_PLUGIN_COMMAND_BUFFER_STUB_H_ +#define CHROME_PLUGIN_COMMAND_BUFFER_STUB_H_ +#pragma once + +#if defined(ENABLE_GPU) + +#include "app/surface/transport_dib.h" +#include "base/ref_counted.h" +#include "gpu/command_buffer/common/command_buffer.h" +#include "gpu/command_buffer/service/command_buffer_service.h" +#include "gpu/command_buffer/service/gpu_processor.h" +#include "ipc/ipc_channel.h" +#include "ipc/ipc_message.h" +#include "ui/gfx/native_widget_types.h" + +class PluginChannel; + +class CommandBufferService; + +class CommandBufferStub : public IPC::Channel::Listener, + public IPC::Message::Sender { + public: + CommandBufferStub(PluginChannel* channel, + int plugin_host_route_id, + gfx::PluginWindowHandle window); + + virtual ~CommandBufferStub(); + + // IPC::Channel::Listener implementation: + virtual bool OnMessageReceived(const IPC::Message& message); + virtual void OnChannelError(); + + // IPC::Message::Sender implementation: + virtual bool Send(IPC::Message* msg); + + int route_id() const { return route_id_; } + + // Notify the client that it must repaint due to the window becoming invalid + // or a lost context. + void NotifyRepaint(); + + private: + // Message handlers: + void OnInitialize(base::SharedMemoryHandle ring_buffer, + int32 size, + bool* result); + void OnGetState(gpu::CommandBuffer::State* state); + void OnAsyncGetState(); + void OnFlush(int32 put_offset, gpu::CommandBuffer::State* state); + void OnAsyncFlush(int32 put_offset); + void OnCreateTransferBuffer(int32 size, int32* id); + void OnDestroyTransferBuffer(int32 id); + void OnGetTransferBuffer(int32 id, + base::SharedMemoryHandle* transfer_buffer, + uint32* size); + + // Destroy all owned objects. + void Destroy(); + + bool InitializePlatformSpecific(); + void DestroyPlatformSpecific(); + +#if defined(OS_MACOSX) + void OnSetWindowSize(const gfx::Size& size); + void SwapBuffersCallback(); + void AllocTransportDIB(const size_t size, TransportDIB::Handle* dib_handle); + void FreeTransportDIB(TransportDIB::Id dib_id); +#endif + + scoped_refptr<PluginChannel> channel_; + int plugin_host_route_id_; + gfx::PluginWindowHandle window_; + int route_id_; + scoped_ptr<gpu::CommandBufferService> command_buffer_; + scoped_ptr<gpu::GPUProcessor> processor_; +}; + +#endif // ENABLE_GPU + +#endif // CHROME_PLUGIN_COMMAND_BUFFER_STUB_H_ diff --git a/chrome/plugin/command_buffer_stub_win.cc b/chrome/plugin/command_buffer_stub_win.cc new file mode 100644 index 0000000..11369a6 --- /dev/null +++ b/chrome/plugin/command_buffer_stub_win.cc @@ -0,0 +1,73 @@ +// Copyright (c) 2010 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 <windows.h> + +#include "chrome/plugin/command_buffer_stub.h" + +namespace { +const wchar_t* kPreviousWndProcProperty = L"CommandBufferStubPrevWndProc"; +const wchar_t* kCommandBufferStubProperty = L"CommandBufferStub"; + +// Message handler for the GPU plugin's child window. Used to intercept +// WM_PAINT events and forward repaint notifications to the client. +LRESULT WINAPI WndProc(HWND handle, + UINT message, + WPARAM w_param, + LPARAM l_param) { + WNDPROC previous_wnd_proc = reinterpret_cast<WNDPROC>( + ::GetProp(handle, kPreviousWndProcProperty)); + CommandBufferStub* stub = reinterpret_cast<CommandBufferStub*>( + ::GetProp(handle, kCommandBufferStubProperty)); + + switch (message) { + case WM_ERASEBKGND: + // Do not clear background. Avoids flickering. + return 1; + case WM_PAINT: + // Validate the whole window to prevent another WM_PAINT message. + ValidateRect(handle, NULL); + + // Notify client that the window is invalid and needs to be repainted. + stub->NotifyRepaint(); + + return 1; + default: + return CallWindowProc(previous_wnd_proc, + handle, + message, + w_param, + l_param); + } +} +} // namespace anonymous + +bool CommandBufferStub::InitializePlatformSpecific() { + // Subclass window. + WNDPROC previous_wnd_proc = reinterpret_cast<WNDPROC>( + ::GetWindowLongPtr(window_, GWLP_WNDPROC)); + ::SetProp(window_, + kPreviousWndProcProperty, + reinterpret_cast<HANDLE>(previous_wnd_proc)); + ::SetWindowLongPtr(window_, + GWLP_WNDPROC, + reinterpret_cast<LONG_PTR>(WndProc)); + + // Record pointer to this in window. + ::SetProp(window_, + kCommandBufferStubProperty, + reinterpret_cast<HANDLE>(this)); + + return true; +} + +void CommandBufferStub::DestroyPlatformSpecific() { + // Restore window. + WNDPROC previous_wnd_proc = reinterpret_cast<WNDPROC>( + ::GetProp(window_, kPreviousWndProcProperty)); + ::SetWindowLongPtr(window_, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>( + previous_wnd_proc)); + ::RemoveProp(window_, kPreviousWndProcProperty); + ::RemoveProp(window_, kCommandBufferStubProperty); +} diff --git a/chrome/plugin/plugin_main.cc b/chrome/plugin/plugin_main.cc index d8264fe..5c94e52 100644 --- a/chrome/plugin/plugin_main.cc +++ b/chrome/plugin/plugin_main.cc @@ -17,6 +17,7 @@ #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/default_plugin.h" +#include "chrome/common/gpu_plugin.h" #include "chrome/common/hi_res_timer_manager.h" #include "chrome/common/logging_chrome.h" #include "chrome/common/main_function_params.h" @@ -173,6 +174,7 @@ int PluginMain(const MainFunctionParams& parameters) { #endif chrome::RegisterInternalDefaultPlugin(); + chrome::RegisterInternalGPUPlugin(); MessageLoop::current()->Run(); } diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc index 0624e3e..75a3dc8 100644 --- a/chrome/plugin/webplugin_delegate_stub.cc +++ b/chrome/plugin/webplugin_delegate_stub.cc @@ -28,6 +28,10 @@ #include "printing/native_metafile.h" #endif // defined(OS_WIN) +#if defined(ENABLE_GPU) +#include "app/gfx/gl/gl_context.h" +#endif + using WebKit::WebBindings; using WebKit::WebCursorInfo; using webkit::npapi::WebPlugin; @@ -68,6 +72,13 @@ WebPluginDelegateStub::~WebPluginDelegateStub() { in_destructor_ = true; child_process_logging::SetActiveURL(page_url_); +#if defined(ENABLE_GPU) + // Make sure there is no command buffer before destroying the window handle. + // The GPU service code might otherwise asynchronously perform an operation + // using the window handle. + command_buffer_stub_.reset(); +#endif + if (channel_->in_send()) { // The delegate or an npobject is in the callstack, so don't delete it // right away. @@ -133,6 +144,10 @@ bool WebPluginDelegateStub::OnMessageReceived(const IPC::Message& msg) { OnHandleURLRequestReply) IPC_MESSAGE_HANDLER(PluginMsg_HTTPRangeRequestReply, OnHTTPRangeRequestReply) + IPC_MESSAGE_HANDLER(PluginMsg_CreateCommandBuffer, + OnCreateCommandBuffer) + IPC_MESSAGE_HANDLER(PluginMsg_DestroyCommandBuffer, + OnDestroyCommandBuffer) #if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(PluginMsg_SetFakeAcceleratedSurfaceWindowHandle, OnSetFakeAcceleratedSurfaceWindowHandle) @@ -401,6 +416,29 @@ void WebPluginDelegateStub::OnInstallMissingPlugin() { delegate_->InstallMissingPlugin(); } +void WebPluginDelegateStub::OnCreateCommandBuffer(int* route_id) { + *route_id = 0; +#if defined(ENABLE_GPU) + // Fail to create the command buffer if some GL implementation cannot be + // initialized. + if (!gfx::GLContext::InitializeOneOff()) + return; + + command_buffer_stub_.reset(new CommandBufferStub( + channel_, + instance_id_, + delegate_->windowed_handle())); + + *route_id = command_buffer_stub_->route_id(); +#endif // ENABLE_GPU +} + +void WebPluginDelegateStub::OnDestroyCommandBuffer() { +#if defined(ENABLE_GPU) + command_buffer_stub_.reset(); +#endif +} + void WebPluginDelegateStub::CreateSharedBuffer( uint32 size, base::SharedMemory* shared_buf, diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h index b56bca7..e769a84 100644 --- a/chrome/plugin/webplugin_delegate_stub.h +++ b/chrome/plugin/webplugin_delegate_stub.h @@ -12,10 +12,10 @@ #include "base/ref_counted.h" #include "base/shared_memory.h" #include "base/task.h" +#include "chrome/plugin/command_buffer_stub.h" #include "googleurl/src/gurl.h" #include "ipc/ipc_channel.h" #include "third_party/npapi/bindings/npapi.h" -#include "ui/gfx/native_widget_types.h" #include "ui/gfx/rect.h" class PluginChannel; @@ -103,6 +103,8 @@ class WebPluginDelegateStub : public IPC::Channel::Listener, const GURL& url, int notify_id); void OnHTTPRangeRequestReply(unsigned long resource_id, int range_request_id); + void OnCreateCommandBuffer(int* route_id); + void OnDestroyCommandBuffer(); void CreateSharedBuffer(uint32 size, base::SharedMemory* shared_buf, @@ -121,12 +123,17 @@ class WebPluginDelegateStub : public IPC::Channel::Listener, GURL page_url_; #if defined(ENABLE_GPU) + // If this is the GPU plugin, the stub object that forwards to the + // command buffer service. + scoped_ptr<CommandBufferStub> command_buffer_stub_; + #if defined(OS_MACOSX) // If this is a GPU-accelerated plug-in, we need to be able to receive a fake // window handle which is used for subsequent communication back to the // browser. void OnSetFakeAcceleratedSurfaceWindowHandle(gfx::PluginWindowHandle window); #endif + #endif DISALLOW_IMPLICIT_CONSTRUCTORS(WebPluginDelegateStub); diff --git a/chrome/renderer/webplugin_delegate_pepper.cc b/chrome/renderer/webplugin_delegate_pepper.cc index 7a9e4ea..43709f8 100644 --- a/chrome/renderer/webplugin_delegate_pepper.cc +++ b/chrome/renderer/webplugin_delegate_pepper.cc @@ -63,6 +63,14 @@ #include "ui/gfx/gdi_util.h" #endif +#if defined(ENABLE_GPU) +#include "webkit/plugins/npapi/plugin_constants_win.h" +#endif + +#if defined(ENABLE_GPU) +using gpu::Buffer; +#endif + using webkit::npapi::WebPlugin; using webkit::npapi::WebPluginDelegate; using webkit::npapi::WebPluginResourceClient; @@ -79,6 +87,15 @@ struct Device2DImpl { TransportDIB* dib; }; +struct Device3DImpl { +#if defined(ENABLE_GPU) + gpu::CommandBuffer* command_buffer; +#endif + bool dynamically_created; +}; + +const int32 kDefaultCommandBufferSize = 1024 * 1024; + } // namespace static const float kPointsPerInch = 72.0; @@ -180,6 +197,22 @@ void WebPluginDelegatePepper::DestroyInstance() { instance_ = 0; } + + // Destroy the nested GPU plugin only after first destroying the underlying + // Pepper plugin. This is so the Pepper plugin does not attempt to issue + // rendering commands after the GPU plugin has stopped processing them and + // responding to them. + if (nested_delegate_) { +#if defined(ENABLE_GPU) + if (command_buffer_) { + nested_delegate_->DestroyCommandBuffer(command_buffer_); + command_buffer_ = NULL; + } +#endif + + nested_delegate_->PluginDestroyed(); + nested_delegate_ = NULL; + } } void WebPluginDelegatePepper::UpdateGeometry( @@ -204,6 +237,21 @@ 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 defined(ENABLE_GPU) +#if defined(OS_MACOSX) + // Send the new window size to the command buffer service code so it + // can allocate a new backing store. The handle to the new backing + // store is sent back to the browser asynchronously. + if (command_buffer_) { + command_buffer_->SetWindowSize(window_rect_.size()); + } +#endif // OS_MACOSX +#endif // ENABLE_GPU + if (!instance()) return; @@ -519,7 +567,8 @@ NPError WebPluginDelegatePepper::Device2DInitializeContext( } // This is a windowless plugin, so set it to have no handle. Defer this - // until we know the plugin will use the 2D device. + // until we know the plugin will use the 2D device. If it uses the 3D device + // it will have a window handle. plugin_->SetWindow(gfx::kNullPluginWindow); scoped_ptr<Graphics2DDeviceContext> g2d(new Graphics2DDeviceContext(this)); @@ -620,6 +669,76 @@ NPError WebPluginDelegatePepper::Device3DQueryConfig( NPError WebPluginDelegatePepper::Device3DInitializeContext( const NPDeviceContext3DConfig* config, NPDeviceContext3D* context) { + if (!context) + return NPERR_GENERIC_ERROR; + +#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( + "application/vnd.google.chrome.gpu-plugin", 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)) { + plugin_->SetAcceptsInputEvents(true); + + // Ensure the window has the correct size before initializing the + // command buffer. + nested_delegate_->UpdateGeometry(window_rect_, clip_rect_); + + // Ask the GPU plugin to create a command buffer and return a proxy. + command_buffer_ = nested_delegate_->CreateCommandBuffer(); + if (command_buffer_) { + // Initialize the proxy command buffer. + if (command_buffer_->Initialize(config->commandBufferSize)) { + // Get the initial command buffer state. + gpu::CommandBuffer::State state = command_buffer_->GetState(); + + // Initialize the 3D context. + context->reserved = NULL; + context->waitForProgress = true; + Buffer ring_buffer = command_buffer_->GetRingBuffer(); + context->commandBuffer = ring_buffer.ptr; + context->commandBufferSize = state.num_entries; + context->repaintCallback = NULL; + Synchronize3DContext(context, state); + + ScheduleHandleRepaint(instance_->npp(), context); + +#if defined(OS_MACOSX) + command_buffer_->SetWindowSize(window_rect_.size()); +#endif // OS_MACOSX + + // Make sure the nested delegate shows up in the right place + // on the page. + SendNestedDelegateGeometryToBrowser(window_rect_, clip_rect_); + + // Save the implementation information (the CommandBuffer). + Device3DImpl* impl = new Device3DImpl; + impl->command_buffer = command_buffer_; + impl->dynamically_created = false; + context->reserved = impl; + + return NPERR_NO_ERROR; + } + + nested_delegate_->DestroyCommandBuffer(command_buffer_); + command_buffer_ = NULL; + } + } + + nested_delegate_->PluginDestroyed(); + nested_delegate_ = NULL; +#endif // ENABLE_GPU + return NPERR_GENERIC_ERROR; } @@ -642,49 +761,212 @@ NPError WebPluginDelegatePepper::Device3DFlushContext( NPDeviceContext3D* context, NPDeviceFlushContextCallbackPtr callback, void* user_data) { - return NPERR_GENERIC_ERROR; + if (!context) + return NPERR_GENERIC_ERROR; + +#if defined(ENABLE_GPU) + gpu::CommandBuffer::State state; + + if (context->waitForProgress) { + if (callback) { + command_buffer_->AsyncFlush( + context->putOffset, + method_factory3d_.NewRunnableMethod( + &WebPluginDelegatePepper::Device3DUpdateState, + id, + context, + callback, + user_data)); + } else { + state = command_buffer_->FlushSync(context->putOffset); + Synchronize3DContext(context, state); + } + } else { + if (callback) { + command_buffer_->AsyncGetState( + method_factory3d_.NewRunnableMethod( + &WebPluginDelegatePepper::Device3DUpdateState, + id, + context, + callback, + user_data)); + } else { + state = command_buffer_->GetState(); + Synchronize3DContext(context, state); + } + } +#endif // ENABLE_GPU + return NPERR_NO_ERROR; } NPError WebPluginDelegatePepper::Device3DDestroyContext( NPDeviceContext3D* context) { - return NPERR_GENERIC_ERROR; + if (!context) + return NPERR_GENERIC_ERROR; + +#if defined(ENABLE_GPU) + // Prevent any async flush callbacks from being invoked after the context + // has been destroyed. + method_factory3d_.RevokeAll(); + + // TODO(apatrick): this will be much simpler when we switch to the new device + // API. There should be no need for the Device3DImpl and the context will + // always be destroyed dynamically. + Device3DImpl* impl = static_cast<Device3DImpl*>(context->reserved); + bool dynamically_created = impl->dynamically_created; + delete impl; + context->reserved = NULL; + if (dynamically_created) { + delete context; + } + + if (nested_delegate_) { + if (command_buffer_) { + nested_delegate_->DestroyCommandBuffer(command_buffer_); + command_buffer_ = NULL; + } + + nested_delegate_->PluginDestroyed(); + nested_delegate_ = NULL; + } +#endif // ENABLE_GPU + + return NPERR_NO_ERROR; } NPError WebPluginDelegatePepper::Device3DCreateBuffer( NPDeviceContext3D* context, size_t size, int32* id) { - return NPERR_GENERIC_ERROR; + if (!context) + return NPERR_GENERIC_ERROR; + +#if defined(ENABLE_GPU) + *id = command_buffer_->CreateTransferBuffer(size); + if (*id < 0) + return NPERR_GENERIC_ERROR; +#endif // ENABLE_GPU + + return NPERR_NO_ERROR; } NPError WebPluginDelegatePepper::Device3DDestroyBuffer( NPDeviceContext3D* context, int32 id) { - return NPERR_GENERIC_ERROR; + if (!context) + return NPERR_GENERIC_ERROR; + +#if defined(ENABLE_GPU) + command_buffer_->DestroyTransferBuffer(id); +#endif // ENABLE_GPU + return NPERR_NO_ERROR; } NPError WebPluginDelegatePepper::Device3DMapBuffer( NPDeviceContext3D* context, int32 id, NPDeviceBuffer* np_buffer) { - return NPERR_GENERIC_ERROR; + if (!context) + return NPERR_GENERIC_ERROR; + +#if defined(ENABLE_GPU) + Buffer gpu_buffer; + if (id == NP3DCommandBufferId) { + gpu_buffer = command_buffer_->GetRingBuffer(); + } else { + 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; } NPError WebPluginDelegatePepper::Device3DGetNumConfigs(int32* num_configs) { - return NPERR_GENERIC_ERROR; + if (!num_configs) + return NPERR_GENERIC_ERROR; + + *num_configs = 1; + return NPERR_NO_ERROR; } NPError WebPluginDelegatePepper::Device3DGetConfigAttribs( int32 config, int32* attrib_list) { - return NPERR_GENERIC_ERROR; + // Only one config available currently. + if (config != 0) + return NPERR_GENERIC_ERROR; + + if (attrib_list) { + for (int32* attrib_pair = attrib_list; *attrib_pair; attrib_pair += 2) { + switch (attrib_pair[0]) { + case NP3DAttrib_BufferSize: + attrib_pair[1] = 32; + break; + case NP3DAttrib_AlphaSize: + case NP3DAttrib_BlueSize: + case NP3DAttrib_GreenSize: + case NP3DAttrib_RedSize: + attrib_pair[1] = 8; + break; + case NP3DAttrib_DepthSize: + attrib_pair[1] = 24; + break; + case NP3DAttrib_StencilSize: + attrib_pair[1] = 8; + break; + case NP3DAttrib_SurfaceType: + attrib_pair[1] = 0; + break; + default: + return NPERR_GENERIC_ERROR; + } + } + } + + return NPERR_NO_ERROR; } NPError WebPluginDelegatePepper::Device3DCreateContext( int32 config, const int32* attrib_list, NPDeviceContext3D** context) { - return NPERR_GENERIC_ERROR; + if (!context) + return NPERR_GENERIC_ERROR; + + // Only one config available currently. + if (config != 0) + return NPERR_GENERIC_ERROR; + + // For now, just use the old API to initialize the context. + NPDeviceContext3DConfig old_config; + old_config.commandBufferSize = kDefaultCommandBufferSize; + if (attrib_list) { + for (const int32* attrib_pair = attrib_list; *attrib_pair; + attrib_pair += 2) { + switch (attrib_pair[0]) { + case NP3DAttrib_CommandBufferSize: + old_config.commandBufferSize = attrib_pair[1]; + break; + default: + return NPERR_GENERIC_ERROR; + } + } + } + + *context = new NPDeviceContext3D; + Device3DInitializeContext(&old_config, *context); + + // Flag the context as dynamically created by the browser. TODO(apatrick): + // take this out when all contexts are dynamically created. + Device3DImpl* impl = static_cast<Device3DImpl*>((*context)->reserved); + impl->dynamically_created = true; + + return NPERR_NO_ERROR; } NPError WebPluginDelegatePepper::Device3DRegisterCallback( @@ -693,7 +975,19 @@ NPError WebPluginDelegatePepper::Device3DRegisterCallback( int32 callback_type, NPDeviceGenericCallbackPtr callback, void* callback_data) { - return NPERR_GENERIC_ERROR; + if (!context) + return NPERR_GENERIC_ERROR; + + switch (callback_type) { + case NP3DCallback_Repaint: + context->repaintCallback = reinterpret_cast<NPDeviceContext3DRepaintPtr>( + callback); + break; + default: + return NPERR_GENERIC_ERROR; + } + + return NPERR_NO_ERROR; } NPError WebPluginDelegatePepper::Device3DSynchronizeContext( @@ -704,7 +998,58 @@ NPError WebPluginDelegatePepper::Device3DSynchronizeContext( int32* output_attrib_list, NPDeviceSynchronizeContextCallbackPtr callback, void* callback_data) { - return NPERR_GENERIC_ERROR; + if (!context) + return NPERR_GENERIC_ERROR; + + // Copy input attributes into context. + if (input_attrib_list) { + for (const int32* attrib_pair = input_attrib_list; + *attrib_pair; + attrib_pair += 2) { + switch (attrib_pair[0]) { + case NP3DAttrib_PutOffset: + context->putOffset = attrib_pair[1]; + break; + default: + return NPERR_GENERIC_ERROR; + } + } + } + + // Use existing flush mechanism for now. + if (mode != NPDeviceSynchronizationMode_Cached) { + context->waitForProgress = mode == NPDeviceSynchronizationMode_Flush; + Device3DFlushContext(id, context, callback, callback_data); + } + + // Copy most recent output attributes from context. + // To read output attributes after the completion of an asynchronous flush, + // invoke SynchronizeContext again with mode + // NPDeviceSynchronizationMode_Cached from the callback function. + if (output_attrib_list) { + for (int32* attrib_pair = output_attrib_list; + *attrib_pair; + attrib_pair += 2) { + switch (attrib_pair[0]) { + case NP3DAttrib_CommandBufferSize: + attrib_pair[1] = context->commandBufferSize; + break; + case NP3DAttrib_GetOffset: + attrib_pair[1] = context->getOffset; + break; + case NP3DAttrib_PutOffset: + attrib_pair[1] = context->putOffset; + break; + case NP3DAttrib_Token: + attrib_pair[1] = context->token; + break; + default: + return NPERR_GENERIC_ERROR; + } + } + } + + return NPERR_NO_ERROR; } NPError WebPluginDelegatePepper::DeviceAudioQueryCapability(int32 capability, @@ -1038,11 +1383,16 @@ WebPluginDelegatePepper::WebPluginDelegatePepper( : render_view_(render_view), plugin_(NULL), instance_(instance), + nested_delegate_(NULL), current_printer_dpi_(-1), #if defined (OS_LINUX) num_pages_(0), pdf_output_done_(false), #endif // (OS_LINUX) +#if defined(ENABLE_GPU) + command_buffer_(NULL), + method_factory3d_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), +#endif find_identifier_(-1), current_choose_file_callback_(NULL), current_choose_file_user_data_(NULL) { @@ -1080,16 +1430,21 @@ void WebPluginDelegatePepper::PluginDestroyed() { void WebPluginDelegatePepper::Paint(WebKit::WebCanvas* canvas, const gfx::Rect& rect) { - // Blit from background_context to context. - if (!committed_bitmap_.isNull()) { + 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()) { #if defined(OS_MACOSX) - DrawSkBitmapToCanvas(committed_bitmap_, canvas, window_rect_, - static_cast<int>(CGBitmapContextGetHeight(canvas))); + DrawSkBitmapToCanvas(committed_bitmap_, canvas, window_rect_, + static_cast<int>(CGBitmapContextGetHeight(canvas))); #else - canvas->drawBitmap(committed_bitmap_, - SkIntToScalar(window_rect_.origin().x()), - SkIntToScalar(window_rect_.origin().y())); + canvas->drawBitmap(committed_bitmap_, + SkIntToScalar(window_rect_.origin().x()), + SkIntToScalar(window_rect_.origin().y())); #endif + } } } @@ -1229,6 +1584,70 @@ bool WebPluginDelegatePepper::HandleInputEvent(const WebInputEvent& event, return rv; } +#if defined(ENABLE_GPU) + +void WebPluginDelegatePepper::ScheduleHandleRepaint( + NPP npp, NPDeviceContext3D* context) { + command_buffer_->SetNotifyRepaintTask(method_factory3d_.NewRunnableMethod( + &WebPluginDelegatePepper::ForwardHandleRepaint, + npp, + context)); +} + +void WebPluginDelegatePepper::ForwardHandleRepaint( + NPP npp, NPDeviceContext3D* context) { + if (context->repaintCallback) + context->repaintCallback(npp, context); + ScheduleHandleRepaint(npp, context); +} + +void WebPluginDelegatePepper::Synchronize3DContext( + NPDeviceContext3D* context, + const gpu::CommandBuffer::State& state) { + context->getOffset = state.get_offset; + context->putOffset = state.put_offset; + context->token = state.token; + context->error = static_cast<NPDeviceContext3DError>(state.error); +} + +void WebPluginDelegatePepper::Device3DUpdateState( + NPP npp, + NPDeviceContext3D* context, + NPDeviceFlushContextCallbackPtr callback, + void* user_data) { + if (command_buffer_) { + Synchronize3DContext(context, command_buffer_->GetLastState()); + if (callback) + callback(npp, context, NPERR_NO_ERROR, user_data); + } +} + +#endif // ENABLE_GPU + +void WebPluginDelegatePepper::SendNestedDelegateGeometryToBrowser( + const gfx::Rect& window_rect, + const gfx::Rect& clip_rect) { + // Inform the browser about the location of the plugin on the page. + // It appears that initially the plugin does not get laid out correctly -- + // possibly due to lazy creation of the nested delegate. + if (!nested_delegate_ || + !nested_delegate_->GetPluginWindowHandle() || + !render_view_) { + return; + } + + webkit::npapi::WebPluginGeometry geom; + geom.window = nested_delegate_->GetPluginWindowHandle(); + geom.window_rect = window_rect; + geom.clip_rect = clip_rect; + // Rects_valid must be true for this to work in the Gtk port; + // hopefully not having the cutout rects will not cause incorrect + // clipping. + geom.rects_valid = true; + geom.visible = true; + render_view_->DidMovePlugin(geom); +} + bool WebPluginDelegatePepper::CalculatePrintedPageDimensions( int page_number, NPPPrintExtensions* print_extensions, diff --git a/chrome/renderer/webplugin_delegate_pepper.h b/chrome/renderer/webplugin_delegate_pepper.h index 9dbeb1a..81a5d67 100644 --- a/chrome/renderer/webplugin_delegate_pepper.h +++ b/chrome/renderer/webplugin_delegate_pepper.h @@ -16,6 +16,7 @@ #include "base/weak_ptr.h" #include "base/task.h" #include "chrome/renderer/pepper_devices.h" +#include "chrome/renderer/command_buffer_proxy.h" #include "third_party/npapi/bindings/npapi.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileChooserCompletion.h" @@ -212,6 +213,10 @@ class WebPluginDelegatePepper : public webkit::npapi::WebPluginDelegate, webkit::npapi::PluginInstance *instance); ~WebPluginDelegatePepper(); + // Set a task that calls the repaint callback the next time the window + // is invalid and needs to be repainted. + void ScheduleHandleRepaint(NPP npp, NPDeviceContext3D* context); + //----------------------------------------- // used for windowed and windowless plugins @@ -245,6 +250,27 @@ class WebPluginDelegatePepper : public webkit::npapi::WebPluginDelegate, const gfx::Rect& dest_rect, int canvas_height); #endif // OS_MACOSX +#if defined(ENABLE_GPU) + + void ForwardHandleRepaint(NPP npp, NPDeviceContext3D* context); + + // Synchronize a 3D context state with the service. + void Synchronize3DContext(NPDeviceContext3D* context, + const gpu::CommandBuffer::State& state); + + // Synchronize the 3D context state with the proxy and invoke the async + // flush callback. + void Device3DUpdateState(NPP npp, + NPDeviceContext3D* context, + NPDeviceFlushContextCallbackPtr callback, + void* user_data); +#endif + + // Tells the browser out-of-band where the nested delegate lives on + // the page. + void SendNestedDelegateGeometryToBrowser(const gfx::Rect& window_rect, + const gfx::Rect& clip_rect); + // Returns the selection. If nothing is selected, returns an empty string. // If html is true, it will return a string only if html data is available. string16 GetSelectedText(bool html) const; @@ -270,6 +296,9 @@ class WebPluginDelegatePepper : public webkit::npapi::WebPluginDelegate, // The url with which the plugin was instantiated. std::string plugin_url_; + // The nested GPU plugin. + WebPluginDelegateProxy* nested_delegate_; + // The last printable_area passed in to PrintBegin. We remember this because // we need to stretch the printed raster bitmap to these dimensions. It is // cleared in PrintEnd. @@ -294,6 +323,14 @@ class WebPluginDelegatePepper : public webkit::npapi::WebPluginDelegate, bool pdf_output_done_; #endif // defined(OS_LINUX) +#if defined(ENABLE_GPU) + // The command buffer used to issue commands to the nested GPU plugin. + CommandBufferProxy* command_buffer_; + + // Runnable methods that must be cancelled when the 3D context is destroyed. + ScopedRunnableMethodFactory<WebPluginDelegatePepper> method_factory3d_; +#endif + // The id of the current find operation, or -1 if none is in process. int find_identifier_; diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index 6554c74..bc65843 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -1450,6 +1450,37 @@ bool WebPluginDelegateProxy::BindFakePluginWindowHandle(bool opaque) { } #endif +CommandBufferProxy* WebPluginDelegateProxy::CreateCommandBuffer() { +#if defined(ENABLE_GPU) +#if defined(OS_MACOSX) + if (!BindFakePluginWindowHandle(true)) + return NULL; +#endif + int command_buffer_id; + if (!Send(new PluginMsg_CreateCommandBuffer(instance_id_, + &command_buffer_id))) { + return NULL; + } + + CommandBufferProxy* command_buffer = + new CommandBufferProxy(channel_host_, command_buffer_id); + channel_host_->AddRoute(command_buffer_id, command_buffer, NULL); + return command_buffer; +#else + return NULL; +#endif // ENABLE_GPU +} + +void WebPluginDelegateProxy::DestroyCommandBuffer( + CommandBufferProxy* command_buffer) { + DCHECK(command_buffer); +#if defined(ENABLE_GPU) + Send(new PluginMsg_DestroyCommandBuffer(instance_id_)); + channel_host_->RemoveRoute(command_buffer->route_id()); + delete command_buffer; +#endif +} + gfx::PluginWindowHandle WebPluginDelegateProxy::GetPluginWindowHandle() { return window_; } diff --git a/chrome/renderer/webplugin_delegate_proxy.h b/chrome/renderer/webplugin_delegate_proxy.h index 1c99113..ba9fe88 100644 --- a/chrome/renderer/webplugin_delegate_proxy.h +++ b/chrome/renderer/webplugin_delegate_proxy.h @@ -26,6 +26,7 @@ #include "base/linked_ptr.h" #endif +class CommandBufferProxy; struct NPObject; class NPObjectStub; struct NPVariant_Param; @@ -120,6 +121,9 @@ class WebPluginDelegateProxy virtual webkit::npapi::WebPluginResourceClient* CreateSeekableResourceClient( unsigned long resource_id, int range_request_id); + CommandBufferProxy* CreateCommandBuffer(); + void DestroyCommandBuffer(CommandBufferProxy* command_buffer); + gfx::PluginWindowHandle GetPluginWindowHandle(); protected: diff --git a/chrome/test/ui/pepper_uitest.cc b/chrome/test/ui/pepper_uitest.cc new file mode 100644 index 0000000..f34346d --- /dev/null +++ b/chrome/test/ui/pepper_uitest.cc @@ -0,0 +1,47 @@ +// Copyright (c) 2011 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/file_path.h" + +#include "app/app_switches.h" +#include "base/test/test_timeouts.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/ui/npapi_test_helper.h" +#include "chrome/test/ui_test_utils.h" + +using npapi_test::kTestCompleteCookie; +using npapi_test::kTestCompleteSuccess; + +// Helper class pepper NPAPI tests. +class PepperTester : public NPAPITesterBase { + protected: + PepperTester() : NPAPITesterBase() {} + + virtual void SetUp() { + // TODO(alokp): Remove no-sandbox flag once gpu plugin can run in sandbox. + launch_arguments_.AppendSwitch(switches::kNoSandbox); + launch_arguments_.AppendSwitch(switches::kInternalPepper); + launch_arguments_.AppendSwitch(switches::kEnableGPUPlugin); + // Use Mesa software renderer so it can run on testbots without any + // graphics hardware. + launch_arguments_.AppendSwitchASCII(switches::kUseGL, "osmesa"); + NPAPITesterBase::SetUp(); + } +}; + +// Test that a pepper 3d plugin loads and renders. +// TODO(alokp): Enable the test after making sure it works on all platforms +// and buildbots have OpenGL support. +#if defined(OS_WIN) +// Marked as FAILS (46662): failing on buildbots but passes on trybots. +TEST_F(PepperTester, FAILS_Pepper3D) { + const FilePath dir(FILE_PATH_LITERAL("pepper")); + const FilePath file(FILE_PATH_LITERAL("pepper_3d.html")); + GURL url = ui_test_utils::GetTestUrl(dir, file); + ASSERT_NO_FATAL_FAILURE(NavigateToURL(url)); + WaitForFinish("pepper_3d", "1", url, + kTestCompleteCookie, kTestCompleteSuccess, + TestTimeouts::action_max_timeout_ms()); +} +#endif diff --git a/content/browser/plugin_process_host.cc b/content/browser/plugin_process_host.cc index 83cf193..4d1301a 100644 --- a/content/browser/plugin_process_host.cc +++ b/content/browser/plugin_process_host.cc @@ -221,6 +221,7 @@ bool PluginProcessHost::Init(const webkit::npapi::WebPluginInfo& info, switches::kSilentDumpOnDCHECK, switches::kMemoryProfiling, switches::kEnableStatsTable, + switches::kEnableGPUPlugin, switches::kUseGL, #if defined(OS_CHROMEOS) switches::kLoginProfile, diff --git a/content/browser/plugin_service.cc b/content/browser/plugin_service.cc index 2c775ed..78f994e 100644 --- a/content/browser/plugin_service.cc +++ b/content/browser/plugin_service.cc @@ -23,6 +23,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/default_plugin.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" @@ -133,6 +134,8 @@ PluginService::PluginService() plugin_selection_policy_->StartInit(); #endif + chrome::RegisterInternalGPUPlugin(); + // Start watching for changes in the plugin list. This means watching // for changes in the Windows registry keys and on both Windows and POSIX // watch for changes in the paths that are expected to contain plugins. diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index 0fb7581..87b17a7 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp @@ -221,6 +221,26 @@ ], }, { + 'target_name': 'gpu_plugin', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + 'command_buffer_service', + ], + 'include_dirs': [ + '..', + ], + 'all_dependent_settings': { + 'include_dirs': [ + '..', + ], + }, + 'sources': [ + 'gpu_plugin/gpu_plugin.cc', + 'gpu_plugin/gpu_plugin.h', + ], + }, + { 'target_name': 'gpu_unittests', 'type': 'executable', 'dependencies': [ diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi index e662392..45ca5db 100644 --- a/webkit/glue/webkit_glue.gypi +++ b/webkit/glue/webkit_glue.gypi @@ -510,6 +510,11 @@ '../plugins/ppapi/ppb_open_gl_es_impl.cc', ], }], + ['enable_gpu==1', { + 'dependencies': [ + '<(DEPTH)/gpu/gpu.gyp:gpu_plugin', + ], + }], ['OS!="win"', { 'sources/': [['exclude', '_win\\.cc$']], 'sources!': [ |