diff options
author | kbr@chromium.org <kbr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-30 04:42:21 +0000 |
---|---|---|
committer | kbr@chromium.org <kbr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-30 04:42:21 +0000 |
commit | dc51d1ccc18135493f01464e38ed462825ae8e35 (patch) | |
tree | 2da87df4b40a6b8d413c7c94af91b1900952b9e0 | |
parent | 11a7c5374fc1a712ca52d012fffc26fc10dd3d93 (diff) | |
download | chromium_src-dc51d1ccc18135493f01464e38ed462825ae8e35.zip chromium_src-dc51d1ccc18135493f01464e38ed462825ae8e35.tar.gz chromium_src-dc51d1ccc18135493f01464e38ed462825ae8e35.tar.bz2 |
Render Core Animation plugins through WebKit's compositor rather than
directly to the screen in the browser process.
The new composited code path is now the default, though the old code path
has been left in place under a command line flag while we gain confidence.
Issue 105344 has been filed about removing the old code path.
The new code path does not currently support 10.5. The consequence is that
plugins using the InvalidatingCoreAnimation rendering model will not work
on this version of Mac OS. Pepper 3D is not affected; it now uses a
different rendering path.
Changed the type of IOSurfaces' IDs from uint64 to uint32 in a few places
throughout the code to match the IOSurfaceID typedef in the system header.
This was necessary in order to simplify integration with Chrome's OpenGL
code.
There is a known problem in the new code path with garbage occasionally
being drawn to the plugin's area during live resizing of Core Animation
plugins. Issue 105346 has been filed to track this. It is unclear whether
the additional complexity of the fix that is likely needed is worth it.
Tested manually with the following content, with and without the
--disable-composited-core-animation-plugins flag:
- YouTube (does not trigger this code path)
- Google+ Hangouts
- http://unity3d.com/gallery/demos/live-demos (Unity 3D)
- http://www.erain.com/labs/molehill/ (Stage 3D in Flash 11)
- http://www.nissan-stagejuk3d.com/
(Stage 3D in Flash 11, live resizing; web site is flaky, sometimes
fails to start)
BUG=38967
TEST=manual testing with above test cases
Review URL: http://codereview.chromium.org/8678037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112126 0039d316-1c4b-4281-b951-d872f2087c98
20 files changed, 333 insertions, 79 deletions
diff --git a/content/browser/plugin_process_host.cc b/content/browser/plugin_process_host.cc index f155279..e31d161 100644 --- a/content/browser/plugin_process_host.cc +++ b/content/browser/plugin_process_host.cc @@ -201,6 +201,9 @@ bool PluginProcessHost::Init(const webkit::WebPluginInfo& info, // any associated values) if present in the browser command line static const char* const kSwitchNames[] = { switches::kDisableBreakpad, +#if defined(OS_MACOSX) + switches::kDisableCompositedCoreAnimationPlugins, +#endif switches::kDisableLogging, switches::kEnableDCHECK, switches::kEnableLogging, diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 3950f0a..3dca1b3 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -655,6 +655,9 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( switches::kDisableApplicationCache, switches::kDisableAudio, switches::kDisableBreakpad, +#if defined(OS_MACOSX) + switches::kDisableCompositedCoreAnimationPlugins, +#endif switches::kDisableDataTransferItems, switches::kDisableDatabases, switches::kDisableDesktopNotifications, diff --git a/content/common/plugin_messages.h b/content/common/plugin_messages.h index d5f073c..8ede47c 100644 --- a/content/common/plugin_messages.h +++ b/content/common/plugin_messages.h @@ -382,6 +382,9 @@ IPC_MESSAGE_ROUTED1(PluginHostMsg_FocusChanged, IPC_MESSAGE_ROUTED0(PluginHostMsg_StartIme) +//---------------------------------------------------------------------- +// Legacy Core Animation plugin implementation rendering directly to screen. + // This message, used in Mac OS X 10.5 and earlier, is sent from the plug-in // process to the renderer process to indicate that the plug-in allocated a // new TransportDIB that holds the GPU's rendered image. This information is @@ -435,6 +438,29 @@ IPC_MESSAGE_ROUTED1(PluginHostMsg_FreeTransportDIB, IPC_MESSAGE_ROUTED2(PluginHostMsg_AcceleratedSurfaceBuffersSwapped, gfx::PluginWindowHandle /* window */, uint64 /* surface_id */) + +//---------------------------------------------------------------------- +// New Core Animation plugin implementation rendering via compositor. + +// Notifies the renderer process that this plugin will be using the +// accelerated rendering path. +IPC_MESSAGE_ROUTED0(PluginHostMsg_AcceleratedPluginEnabledRendering) + +// Notifies the renderer process that the plugin allocated a new +// IOSurface into which it is rendering. The renderer process forwards +// this IOSurface to the GPU process, causing it to be bound to a +// texture from which the compositor can render. Any previous +// IOSurface allocated by this plugin must be implicitly released by +// the receipt of this message. +IPC_MESSAGE_ROUTED3(PluginHostMsg_AcceleratedPluginAllocatedIOSurface, + int32 /* width */, + int32 /* height */, + uint32 /* surface_id */) + +// Notifies the renderer process that the plugin produced a new frame +// of content into its IOSurface, and therefore that the compositor +// needs to redraw. +IPC_MESSAGE_ROUTED0(PluginHostMsg_AcceleratedPluginSwappedIOSurface) #endif IPC_MESSAGE_CONTROL1(PluginHostMsg_ClearSiteDataResult, diff --git a/content/plugin/webplugin_accelerated_surface_proxy_mac.cc b/content/plugin/webplugin_accelerated_surface_proxy_mac.cc index 9573a27..65749f0 100644 --- a/content/plugin/webplugin_accelerated_surface_proxy_mac.cc +++ b/content/plugin/webplugin_accelerated_surface_proxy_mac.cc @@ -7,30 +7,53 @@ #include "content/plugin/webplugin_accelerated_surface_proxy_mac.h" #include "base/bind.h" +#include "base/command_line.h" #include "content/plugin/webplugin_proxy.h" +#include "ui/base/ui_base_switches.h" #include "ui/gfx/surface/accelerated_surface_mac.h" +#include "ui/gfx/surface/io_surface_support_mac.h" #include "ui/gfx/surface/transport_dib.h" -WebPluginAcceleratedSurfaceProxy::WebPluginAcceleratedSurfaceProxy( +WebPluginAcceleratedSurfaceProxy* WebPluginAcceleratedSurfaceProxy::Create( WebPluginProxy* plugin_proxy, - gfx::GpuPreference gpu_preference) - : plugin_proxy_(plugin_proxy), - window_handle_(NULL) { - surface_ = new AcceleratedSurface; - // It's possible for OpenGL to fail to initialze (e.g., if an incompatible + gfx::GpuPreference gpu_preference) { + bool composited = !CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableCompositedCoreAnimationPlugins); + + // Require IOSurface support for drawing Core Animation plugins. + if (composited && !IOSurfaceSupport::Initialize()) + return NULL; + + AcceleratedSurface* surface = new AcceleratedSurface; + // It's possible for OpenGL to fail to initialize (e.g., if an incompatible // mode is forced via flags), so handle that gracefully. - if (!surface_->Initialize(NULL, true, gpu_preference)) { - delete surface_; - surface_ = NULL; - return; + if (!surface->Initialize(NULL, true, gpu_preference)) { + delete surface; + surface = NULL; + if (composited) + return NULL; + } + + if (!composited && surface) { + // Only used for 10.5 support, but harmless on 10.6+. + surface->SetTransportDIBAllocAndFree( + base::Bind(&WebPluginProxy::AllocSurfaceDIB, + base::Unretained(plugin_proxy)), + base::Bind(&WebPluginProxy::FreeSurfaceDIB, + base::Unretained(plugin_proxy))); } - // Only used for 10.5 support, but harmless on 10.6+. - surface_->SetTransportDIBAllocAndFree( - base::Bind(&WebPluginProxy::AllocSurfaceDIB, - base::Unretained(plugin_proxy)), - base::Bind(&WebPluginProxy::FreeSurfaceDIB, - base::Unretained(plugin_proxy))); + return new WebPluginAcceleratedSurfaceProxy( + plugin_proxy, surface, composited); +} + +WebPluginAcceleratedSurfaceProxy::WebPluginAcceleratedSurfaceProxy( + WebPluginProxy* plugin_proxy, + AcceleratedSurface* surface, + bool composited) + : plugin_proxy_(plugin_proxy), + surface_(surface), + composited_(composited) { } WebPluginAcceleratedSurfaceProxy::~WebPluginAcceleratedSurfaceProxy() { @@ -46,17 +69,28 @@ void WebPluginAcceleratedSurfaceProxy::SetWindowHandle( window_handle_ = window; } +bool WebPluginAcceleratedSurfaceProxy::IsComposited() { + return composited_; +} + void WebPluginAcceleratedSurfaceProxy::SetSize(const gfx::Size& size) { if (!surface_) return; - uint64 io_surface_id = surface_->SetSurfaceSize(size); - if (io_surface_id) { - plugin_proxy_->SetAcceleratedSurface(window_handle_, size, io_surface_id); + if (composited_) { + uint32 io_surface_id = surface_->SetSurfaceSize(size); + // If allocation fails for some reason, still inform the plugin proxy. + plugin_proxy_->AcceleratedPluginAllocatedIOSurface( + size.width(), size.height(), io_surface_id); } else { - TransportDIB::Handle transport_dib = surface_->SetTransportDIBSize(size); - if (TransportDIB::is_valid_handle(transport_dib)) { - plugin_proxy_->SetAcceleratedDIB(window_handle_, size, transport_dib); + uint32 io_surface_id = surface_->SetSurfaceSize(size); + if (io_surface_id) { + plugin_proxy_->SetAcceleratedSurface(window_handle_, size, io_surface_id); + } else { + TransportDIB::Handle transport_dib = surface_->SetTransportDIBSize(size); + if (TransportDIB::is_valid_handle(transport_dib)) { + plugin_proxy_->SetAcceleratedDIB(window_handle_, size, transport_dib); + } } } } @@ -78,6 +112,10 @@ void WebPluginAcceleratedSurfaceProxy::EndDrawing() { return; surface_->SwapBuffers(); - plugin_proxy_->AcceleratedFrameBuffersDidSwap( - window_handle_, surface_->GetSurfaceId()); + if (composited_) { + plugin_proxy_->AcceleratedPluginSwappedIOSurface(); + } else { + plugin_proxy_->AcceleratedFrameBuffersDidSwap( + window_handle_, surface_->GetSurfaceId()); + } } diff --git a/content/plugin/webplugin_accelerated_surface_proxy_mac.h b/content/plugin/webplugin_accelerated_surface_proxy_mac.h index f0290ba..6abf39f 100644 --- a/content/plugin/webplugin_accelerated_surface_proxy_mac.h +++ b/content/plugin/webplugin_accelerated_surface_proxy_mac.h @@ -19,22 +19,31 @@ class WebPluginAcceleratedSurfaceProxy : public webkit::npapi::WebPluginAcceleratedSurface { public: // Creates a new WebPluginAcceleratedSurfaceProxy that uses plugin_proxy - // to proxy calls. plugin_proxy must outlive this object. - WebPluginAcceleratedSurfaceProxy(WebPluginProxy* plugin_proxy, - gfx::GpuPreference gpu_preference); + // to proxy calls. plugin_proxy must outlive this object. Returns NULL if + // initialization fails. + static WebPluginAcceleratedSurfaceProxy* Create( + WebPluginProxy* plugin_proxy, + gfx::GpuPreference gpu_preference); + virtual ~WebPluginAcceleratedSurfaceProxy(); // WebPluginAcceleratedSurface implementation. virtual void SetWindowHandle(gfx::PluginWindowHandle window) OVERRIDE; + virtual bool IsComposited() OVERRIDE; virtual void SetSize(const gfx::Size& size) OVERRIDE; virtual CGLContextObj context() OVERRIDE; virtual void StartDrawing() OVERRIDE; virtual void EndDrawing() OVERRIDE; private: + WebPluginAcceleratedSurfaceProxy(WebPluginProxy* plugin_proxy, + AcceleratedSurface* surface, + bool composited); + WebPluginProxy* plugin_proxy_; // Weak ref. gfx::PluginWindowHandle window_handle_; AcceleratedSurface* surface_; + bool composited_; DISALLOW_COPY_AND_ASSIGN(WebPluginAcceleratedSurfaceProxy); }; diff --git a/content/plugin/webplugin_proxy.cc b/content/plugin/webplugin_proxy.cc index bd4a36d..5b0ac6d 100644 --- a/content/plugin/webplugin_proxy.cc +++ b/content/plugin/webplugin_proxy.cc @@ -674,8 +674,8 @@ void WebPluginProxy::BindFakePluginWindowHandle(bool opaque) { WebPluginAcceleratedSurface* WebPluginProxy::GetAcceleratedSurface( gfx::GpuPreference gpu_preference) { if (!accelerated_surface_.get()) - accelerated_surface_.reset(new WebPluginAcceleratedSurfaceProxy( - this, gpu_preference)); + accelerated_surface_.reset( + WebPluginAcceleratedSurfaceProxy::Create(this, gpu_preference)); return accelerated_surface_.get(); } @@ -710,6 +710,22 @@ void WebPluginProxy::AllocSurfaceDIB(const size_t size, void WebPluginProxy::FreeSurfaceDIB(TransportDIB::Id dib_id) { Send(new PluginHostMsg_FreeTransportDIB(route_id_, dib_id)); } + +void WebPluginProxy::AcceleratedPluginEnabledRendering() { + Send(new PluginHostMsg_AcceleratedPluginEnabledRendering(route_id_)); +} + +void WebPluginProxy::AcceleratedPluginAllocatedIOSurface(int32 width, + int32 height, + uint32 surface_id) { + Send(new PluginHostMsg_AcceleratedPluginAllocatedIOSurface( + route_id_, width, height, surface_id)); +} + +void WebPluginProxy::AcceleratedPluginSwappedIOSurface() { + Send(new PluginHostMsg_AcceleratedPluginSwappedIOSurface( + route_id_)); +} #endif void WebPluginProxy::OnPaint(const gfx::Rect& damaged_rect) { diff --git a/content/plugin/webplugin_proxy.h b/content/plugin/webplugin_proxy.h index ddd32fa..2c44c94 100644 --- a/content/plugin/webplugin_proxy.h +++ b/content/plugin/webplugin_proxy.h @@ -136,11 +136,14 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { virtual void StartIme() OVERRIDE; - virtual void BindFakePluginWindowHandle(bool opaque) OVERRIDE; - virtual webkit::npapi::WebPluginAcceleratedSurface* GetAcceleratedSurface(gfx::GpuPreference gpu_preference) OVERRIDE; + //---------------------------------------------------------------------- + // Legacy Core Animation plugin implementation rendering directly to screen. + + virtual void BindFakePluginWindowHandle(bool opaque) OVERRIDE; + // Tell the browser (via the renderer) to invalidate because the // accelerated buffers have changed. virtual void AcceleratedFrameBuffersDidSwap( @@ -168,6 +171,20 @@ class WebPluginProxy : public webkit::npapi::WebPlugin { virtual void AllocSurfaceDIB(const size_t size, TransportDIB::Handle* dib_handle); virtual void FreeSurfaceDIB(TransportDIB::Id dib_id); + + //---------------------------------------------------------------------- + // New accelerated plugin implementation which renders via the compositor. + + // Tells the renderer, and from there the GPU process, that the plugin + // is using accelerated rather than software rendering. + virtual void AcceleratedPluginEnabledRendering() OVERRIDE; + + // Tells the renderer, and from there the GPU process, that the plugin + // allocated the given IOSurface to be used as its backing store. + virtual void AcceleratedPluginAllocatedIOSurface(int32 width, + int32 height, + uint32 surface_id) OVERRIDE; + virtual void AcceleratedPluginSwappedIOSurface() OVERRIDE; #endif virtual void URLRedirectResponse(bool allow, int resource_id) OVERRIDE; diff --git a/content/renderer/webplugin_delegate_proxy.cc b/content/renderer/webplugin_delegate_proxy.cc index c47ca68..4d57b17 100644 --- a/content/renderer/webplugin_delegate_proxy.cc +++ b/content/renderer/webplugin_delegate_proxy.cc @@ -169,6 +169,9 @@ WebPluginDelegateProxy::WebPluginDelegateProxy( : render_view_(render_view), plugin_(NULL), uses_shared_bitmaps_(false), +#if defined(OS_MACOSX) + uses_compositor_(false), +#endif window_(gfx::kNullPluginWindow), mime_type_(mime_type), instance_id_(MSG_ROUTING_NONE), @@ -435,6 +438,13 @@ bool WebPluginDelegateProxy::OnMessageReceived(const IPC::Message& msg) { OnAcceleratedSurfaceFreeTransportDIB) IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedSurfaceBuffersSwapped, OnAcceleratedSurfaceBuffersSwapped) + // Used only on 10.6 and later. + IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginEnabledRendering, + OnAcceleratedPluginEnabledRendering) + IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginAllocatedIOSurface, + OnAcceleratedPluginAllocatedIOSurface) + IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginSwappedIOSurface, + OnAcceleratedPluginSwappedIOSurface) #endif IPC_MESSAGE_HANDLER(PluginHostMsg_URLRedirectResponse, OnURLRedirectResponse) @@ -1030,7 +1040,11 @@ void WebPluginDelegateProxy::ImeCompositionCompleted(const string16& text, #endif // OS_MACOSX void WebPluginDelegateProxy::OnSetWindow(gfx::PluginWindowHandle window) { +#if defined(OS_MACOSX) + uses_shared_bitmaps_ = !window && !uses_compositor_; +#else uses_shared_bitmaps_ = !window; +#endif window_ = window; if (plugin_) plugin_->SetWindow(window); @@ -1386,6 +1400,24 @@ void WebPluginDelegateProxy::OnAcceleratedSurfaceBuffersSwapped( if (render_view_) render_view_->AcceleratedSurfaceBuffersSwapped(window, surface_id); } + +void WebPluginDelegateProxy::OnAcceleratedPluginEnabledRendering() { + uses_compositor_ = true; + OnSetWindow(NULL); +} + +void WebPluginDelegateProxy::OnAcceleratedPluginAllocatedIOSurface( + int32 width, + int32 height, + uint32 surface_id) { + if (plugin_) + plugin_->AcceleratedPluginAllocatedIOSurface(width, height, surface_id); +} + +void WebPluginDelegateProxy::OnAcceleratedPluginSwappedIOSurface() { + if (plugin_) + plugin_->AcceleratedPluginSwappedIOSurface(); +} #endif #if defined(OS_WIN) diff --git a/content/renderer/webplugin_delegate_proxy.h b/content/renderer/webplugin_delegate_proxy.h index 5c2592b..d89fd40 100644 --- a/content/renderer/webplugin_delegate_proxy.h +++ b/content/renderer/webplugin_delegate_proxy.h @@ -187,6 +187,13 @@ class WebPluginDelegateProxy void OnAcceleratedSurfaceFreeTransportDIB(TransportDIB::Id dib_id); void OnAcceleratedSurfaceBuffersSwapped(gfx::PluginWindowHandle window, uint64 surface_id); + + // New accelerated plugin implementation. + void OnAcceleratedPluginEnabledRendering(); + void OnAcceleratedPluginAllocatedIOSurface(int32 width, + int32 height, + uint32 surface_id); + void OnAcceleratedPluginSwappedIOSurface(); #endif void OnURLRedirectResponse(bool allow, int resource_id); @@ -270,6 +277,9 @@ class WebPluginDelegateProxy base::WeakPtr<RenderViewImpl> render_view_; webkit::npapi::WebPlugin* plugin_; bool uses_shared_bitmaps_; +#if defined(OS_MACOSX) + bool uses_compositor_; +#endif gfx::PluginWindowHandle window_; scoped_refptr<PluginChannelHost> channel_host_; std::string mime_type_; diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc index 73a5606..9df9957 100644 --- a/ui/base/ui_base_switches.cc +++ b/ui/base/ui_base_switches.cc @@ -14,4 +14,9 @@ const char kLang[] = "lang"; // path should point to a locale.pak file. const char kLocalePak[] = "locale_pak"; +#if defined(OS_MACOSX) +const char kDisableCompositedCoreAnimationPlugins[] = + "disable-composited-core-animation-plugins"; +#endif + } // namespace switches diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h index 27f4f08..2bb97d3 100644 --- a/ui/base/ui_base_switches.h +++ b/ui/base/ui_base_switches.h @@ -8,6 +8,7 @@ #define UI_BASE_UI_BASE_SWITCHES_H_ #pragma once +#include "base/compiler_specific.h" #include "ui/base/ui_export.h" namespace switches { @@ -15,6 +16,15 @@ namespace switches { UI_EXPORT extern const char kLang[]; UI_EXPORT extern const char kLocalePak[]; +#if defined(OS_MACOSX) +// TODO(kbr): remove this and the associated old code path: +// http://crbug.com/105344 +// This isn't really the right place for this switch, but is the most +// convenient place where it can be shared between +// src/webkit/plugins/npapi/ and src/content/plugin/ . +UI_EXPORT extern const char kDisableCompositedCoreAnimationPlugins[]; +#endif + } // namespace switches #endif // UI_BASE_UI_BASE_SWITCHES_H_ diff --git a/ui/gfx/surface/accelerated_surface_mac.cc b/ui/gfx/surface/accelerated_surface_mac.cc index b0fb156..1a0fd31 100644 --- a/ui/gfx/surface/accelerated_surface_mac.cc +++ b/ui/gfx/surface/accelerated_surface_mac.cc @@ -87,9 +87,9 @@ void AcceleratedSurface::SwapBuffers() { if (allocate_fbo_) { // Bind and unbind the framebuffer to make changes to the // IOSurface show up in the other process. - glFlush(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); + glFlush(); } else { // Copy the current framebuffer's contents into our "live" texture. // Note that the current GL context might not be ours at this point! @@ -146,16 +146,24 @@ static void AddIntegerValue(CFMutableDictionaryRef dictionary, CFDictionaryAddValue(dictionary, key, number.get()); } +// Creates a new OpenGL texture object bound to the given texture target. +// Caller owns the returned texture. +static GLuint CreateTexture(GLenum target) { + GLuint texture = 0; + glGenTextures(1, &texture); + glBindTexture(target, texture); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + return texture; +} + void AcceleratedSurface::AllocateRenderBuffers(GLenum target, const gfx::Size& size) { if (!texture_) { // Generate the texture object. - glGenTextures(1, &texture_); - glBindTexture(target, texture_); - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture_ = CreateTexture(target); // Generate and bind the framebuffer object. glGenFramebuffersEXT(1, &fbo_); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); @@ -225,7 +233,7 @@ void AcceleratedSurface::Clear(const gfx::Rect& rect) { glClear(GL_COLOR_BUFFER_BIT); } -uint64 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) { +uint32 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) { if (surface_size_ == size) { // Return 0 to indicate to the caller that no new backing store // allocation occurred. @@ -255,12 +263,7 @@ uint64 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) { AllocateRenderBuffers(target, clamped_size); } else if (!texture_) { // Generate the texture object. - glGenTextures(1, &texture_); - glBindTexture(target, texture_); - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + texture_ = CreateTexture(target); } // Allocate a new IOSurface, which is the GPU resource that can be @@ -315,7 +318,7 @@ uint64 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) { return io_surface_id_; } -uint64 AcceleratedSurface::GetSurfaceId() { +uint32 AcceleratedSurface::GetSurfaceId() { return io_surface_id_; } diff --git a/ui/gfx/surface/accelerated_surface_mac.h b/ui/gfx/surface/accelerated_surface_mac.h index 83c95d6..37f50a7 100644 --- a/ui/gfx/surface/accelerated_surface_mac.h +++ b/ui/gfx/surface/accelerated_surface_mac.h @@ -64,11 +64,11 @@ class SURFACE_EXPORT AcceleratedSurface { // the height or width changes. Returns a unique id of the IOSurface to // which the surface is bound, or 0 if no changes were made or an error // occurred. MakeCurrent() will have been called on the new surface. - uint64 SetSurfaceSize(const gfx::Size& size); + uint32 SetSurfaceSize(const gfx::Size& size); - // Returns the id of this surface's IOSruface, or 0 for + // Returns the id of this surface's IOSurface, or 0 for // transport DIB surfaces. - uint64 GetSurfaceId(); + uint32 GetSurfaceId(); // Sets the GL context to be the current one for drawing. Returns true if // it succeeded. @@ -148,7 +148,7 @@ class SURFACE_EXPORT AcceleratedSurface { base::mac::ScopedCFTypeRef<CFTypeRef> io_surface_; // The id of |io_surface_| or 0 if that's NULL. - uint64 io_surface_id_; + uint32 io_surface_id_; // TODO(dspringer): If we end up keeping this TransportDIB mechanism, this // should really be a scoped_ptr_malloc<>, with a deallocate functor that diff --git a/webkit/plugins/npapi/plugin_host.cc b/webkit/plugins/npapi/plugin_host.cc index bad6fdb..73204d2 100644 --- a/webkit/plugins/npapi/plugin_host.cc +++ b/webkit/plugins/npapi/plugin_host.cc @@ -4,6 +4,7 @@ #include "webkit/plugins/npapi/plugin_host.h" +#include "base/command_line.h" #include "base/file_util.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -16,6 +17,7 @@ #include "third_party/npapi/bindings/npruntime.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h" +#include "ui/base/ui_base_switches.h" #include "ui/gfx/gl/gl_implementation.h" #include "ui/gfx/gl/gl_surface.h" #include "webkit/glue/webkit_glue.h" @@ -71,6 +73,11 @@ static bool SupportsSharingAcceleratedSurfaces() { } return (implementation == gfx::kGLImplementationDesktopGL); } + +static bool UsingCompositedCoreAnimationPlugins() { + return !CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableCompositedCoreAnimationPlugins); +} #endif PluginHost::PluginHost() { @@ -826,8 +833,12 @@ NPError NPN_GetValue(NPP id, NPNVariable variable, void* value) { break; } case NPNVsupportsInvalidatingCoreAnimationBool: { + // The composited code path for this model only works on 10.6 and higher. + // The old direct-to-screen code path supports 10.5. NPBool* supports_model = reinterpret_cast<NPBool*>(value); - *supports_model = true; + bool composited = webkit::npapi::UsingCompositedCoreAnimationPlugins(); + *supports_model = composited ? + webkit::npapi::SupportsSharingAcceleratedSurfaces() : true; rv = NPERR_NO_ERROR; break; } @@ -901,7 +912,9 @@ NPError NPN_SetValue(NPP id, NPPVariable variable, void* value) { case NPPVpluginDrawingModel: { int model = reinterpret_cast<int>(value); if (model == NPDrawingModelCoreGraphics || - model == NPDrawingModelInvalidatingCoreAnimation || + (model == NPDrawingModelInvalidatingCoreAnimation && + (webkit::npapi::SupportsSharingAcceleratedSurfaces() || + !webkit::npapi::UsingCompositedCoreAnimationPlugins())) || (model == NPDrawingModelCoreAnimation && webkit::npapi::SupportsSharingAcceleratedSurfaces())) { plugin->set_drawing_model(static_cast<NPDrawingModel>(model)); diff --git a/webkit/plugins/npapi/webplugin.h b/webkit/plugins/npapi/webplugin.h index 53a2ca4..f861517 100644 --- a/webkit/plugins/npapi/webplugin.h +++ b/webkit/plugins/npapi/webplugin.h @@ -156,6 +156,13 @@ class WebPlugin { // Returns the accelerated surface abstraction for accelerated plugins. virtual WebPluginAcceleratedSurface* GetAcceleratedSurface( gfx::GpuPreference gpu_preference); + + // Composited Core Animation plugin support. + virtual void AcceleratedPluginEnabledRendering() = 0; + virtual void AcceleratedPluginAllocatedIOSurface(int32 width, + int32 height, + uint32 surface_id) = 0; + virtual void AcceleratedPluginSwappedIOSurface() = 0; #endif // Handles NPN_URLRedirectResponse calls issued by plugins in response to diff --git a/webkit/plugins/npapi/webplugin_accelerated_surface_mac.h b/webkit/plugins/npapi/webplugin_accelerated_surface_mac.h index 5c528f3..2f46861 100644 --- a/webkit/plugins/npapi/webplugin_accelerated_surface_mac.h +++ b/webkit/plugins/npapi/webplugin_accelerated_surface_mac.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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. @@ -25,6 +25,10 @@ class WebPluginAcceleratedSurface { // surface. virtual void SetWindowHandle(gfx::PluginWindowHandle window) = 0; + // Indicates whether the new code path which renders the plugins via + // the compositor should be used. + virtual bool IsComposited() = 0; + // Sets the size of the surface. virtual void SetSize(const gfx::Size& size) = 0; diff --git a/webkit/plugins/npapi/webplugin_delegate_impl.h b/webkit/plugins/npapi/webplugin_delegate_impl.h index 97fde32..f811d72 100644 --- a/webkit/plugins/npapi/webplugin_delegate_impl.h +++ b/webkit/plugins/npapi/webplugin_delegate_impl.h @@ -475,6 +475,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { CALayer* layer_; // Used for CA drawing mode. Weak, retained by plug-in. WebPluginAcceleratedSurface* surface_; // Weak ref. + bool composited_; // If CA plugin, whether it's rendering via compositor. CARenderer* renderer_; // Renders layer_ to surface_. scoped_ptr<base::RepeatingTimer<WebPluginDelegateImpl> > redraw_timer_; diff --git a/webkit/plugins/npapi/webplugin_delegate_impl_mac.mm b/webkit/plugins/npapi/webplugin_delegate_impl_mac.mm index 8e0243a..5127eaf 100644 --- a/webkit/plugins/npapi/webplugin_delegate_impl_mac.mm +++ b/webkit/plugins/npapi/webplugin_delegate_impl_mac.mm @@ -267,6 +267,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( buffer_context_(NULL), layer_(nil), surface_(NULL), + composited_(false), renderer_(nil), containing_window_has_focus_(false), initial_window_focus_(false), @@ -402,11 +403,16 @@ bool WebPluginDelegateImpl::PlatformInitialize() { // without any drawing; returning false would be a more confusing user // experience (since it triggers a missing plugin placeholder). if (surface_ && surface_->context()) { + composited_ = surface_->IsComposited(); renderer_ = [[CARenderer rendererWithCGLContext:surface_->context() options:NULL] retain]; [renderer_ setLayer:layer_]; } - plugin_->BindFakePluginWindowHandle(false); + if (composited_) { + plugin_->AcceleratedPluginEnabledRendering(); + } else { + plugin_->BindFakePluginWindowHandle(false); + } } break; } @@ -415,9 +421,10 @@ bool WebPluginDelegateImpl::PlatformInitialize() { break; } - // Let the WebPlugin know that we are windowless (unless this is a - // Core Animation plugin, in which case BindFakePluginWindowHandle will take - // care of setting up the appropriate window handle). + // Let the WebPlugin know that we are windowless, unless this is a Core + // Animation plugin, in which case AcceleratedPluginEnabledRendering + // calls SetWindow. Rendering breaks if SetWindow is called before + // accelerated rendering is enabled. if (!layer_) plugin_->SetWindow(NULL); @@ -1035,7 +1042,8 @@ void WebPluginDelegateImpl::PluginVisibilityChanged() { #endif if (instance()->drawing_model() == NPDrawingModelCoreAnimation) { bool plugin_visible = container_is_visible_ && !clip_rect_.IsEmpty(); - if (plugin_visible && !redraw_timer_->IsRunning() && windowed_handle()) { + if (plugin_visible && !redraw_timer_->IsRunning() && + (composited_ || windowed_handle())) { redraw_timer_->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kCoreAnimationRedrawPeriodMs), this, &WebPluginDelegateImpl::DrawLayerInSurface); @@ -1062,7 +1070,10 @@ void WebPluginDelegateImpl::StartIme() { void WebPluginDelegateImpl::DrawLayerInSurface() { // If we haven't plumbed up the surface yet, don't try to draw. - if (!windowed_handle() || !renderer_) + if (!renderer_) + return; + + if (!composited_ && !windowed_handle()) return; [renderer_ beginFrameAtTime:CACurrentMediaTime() timeStamp:NULL]; @@ -1084,8 +1095,10 @@ void WebPluginDelegateImpl::DrawLayerInSurface() { // Update the size of the surface to match the current size of the plug-in. void WebPluginDelegateImpl::UpdateAcceleratedSurface() { - // Will only have a window handle when using a Core Animation drawing model. - if (!windowed_handle() || !layer_) + if (!surface_ || !layer_) + return; + + if (!composited_ && !windowed_handle()) return; [CATransaction begin]; @@ -1097,10 +1110,15 @@ void WebPluginDelegateImpl::UpdateAcceleratedSurface() { [renderer_ setBounds:[layer_ bounds]]; surface_->SetSize(window_rect_.size()); + if (composited_) { + // Kick off the drawing timer, if necessary. + PluginVisibilityChanged(); + } } void WebPluginDelegateImpl::set_windowed_handle( gfx::PluginWindowHandle handle) { + DCHECK(!composited_); windowed_handle_ = handle; surface_->SetWindowHandle(handle); UpdateAcceleratedSurface(); diff --git a/webkit/plugins/npapi/webplugin_impl.cc b/webkit/plugins/npapi/webplugin_impl.cc index b78aeab..3ea5256 100644 --- a/webkit/plugins/npapi/webplugin_impl.cc +++ b/webkit/plugins/npapi/webplugin_impl.cc @@ -489,38 +489,31 @@ WebPluginImpl::~WebPluginImpl() { } void WebPluginImpl::SetWindow(gfx::PluginWindowHandle window) { -#if defined(OS_MACOSX) - // The only time this is called twice, and the second time with a - // non-zero PluginWindowHandle, is the case when this WebPluginImpl - // is created on behalf of the GPU plugin. This entire code path - // will go away soon, as soon as the GPU plugin becomes the GPU - // process, so it is being separated out for easy deletion. - - // The logic we want here is: if (window) DCHECK(!window_); - DCHECK(!(window_ && window)); - window_ = window; - // Lie to ourselves about being windowless even if we got a fake - // plugin window handle, so we continue to get input events. - windowless_ = true; - accepts_input_events_ = true; - // We do not really need to notify the page delegate that a plugin - // window was created -- so don't. -#else if (window) { DCHECK(!windowless_); window_ = window; +#if defined(OS_MACOSX) + // TODO(kbr): remove. http://crbug.com/105344 + + // Lie to ourselves about being windowless even if we got a fake + // plugin window handle, so we continue to get input events. + windowless_ = true; + accepts_input_events_ = true; + // We do not really need to notify the page delegate that a plugin + // window was created -- so don't. +#else accepts_input_events_ = false; if (page_delegate_) { // Tell the view delegate that the plugin window was created, so that it // can create necessary container widgets. page_delegate_->CreatedPluginWindow(window); } +#endif } else { DCHECK(!window_); // Make sure not called twice. windowless_ = true; accepts_input_events_ = true; } -#endif } void WebPluginImpl::SetAcceptsInputEvents(bool accepts) { @@ -754,6 +747,39 @@ void WebPluginImpl::URLRedirectResponse(bool allow, int resource_id) { } } +#if defined(OS_MACOSX) +void WebPluginImpl::AcceleratedPluginEnabledRendering() { +} + +void WebPluginImpl::AcceleratedPluginAllocatedIOSurface(int32 width, + int32 height, + uint32 surface_id) { + next_io_surface_allocated_ = true; + next_io_surface_width_ = width; + next_io_surface_height_ = height; + next_io_surface_id_ = surface_id; +} + +void WebPluginImpl::AcceleratedPluginSwappedIOSurface() { + if (container_) { + // Deferring the call to setBackingIOSurfaceId is an attempt to + // work around garbage occasionally showing up in the plugin's + // area during live resizing of Core Animation plugins. The + // assumption was that by the time this was called, the plugin + // process would have populated the newly allocated IOSurface. It + // is not 100% clear at this point why any garbage is getting + // through. More investigation is needed. http://crbug.com/105346 + if (next_io_surface_allocated_) { + container_->setBackingIOSurfaceId(next_io_surface_width_, + next_io_surface_height_, + next_io_surface_id_); + next_io_surface_allocated_ = false; + } + container_->commitBackingTexture(); + } +} +#endif + void WebPluginImpl::Invalidate() { if (container_) container_->invalidate(); diff --git a/webkit/plugins/npapi/webplugin_impl.h b/webkit/plugins/npapi/webplugin_impl.h index c9c798c..ec0f30f 100644 --- a/webkit/plugins/npapi/webplugin_impl.h +++ b/webkit/plugins/npapi/webplugin_impl.h @@ -109,6 +109,13 @@ class WebPluginImpl : public WebPlugin, virtual std::string GetCookies(const GURL& url, const GURL& first_party_for_cookies) OVERRIDE; virtual void URLRedirectResponse(bool allow, int resource_id) OVERRIDE; +#if defined(OS_MACOSX) + virtual void AcceleratedPluginEnabledRendering() OVERRIDE; + virtual void AcceleratedPluginAllocatedIOSurface(int32 width, + int32 height, + uint32 surface_id) OVERRIDE; + virtual void AcceleratedPluginSwappedIOSurface() OVERRIDE; +#endif // Given a (maybe partial) url, completes using the base url. GURL CompleteURL(const char* url); @@ -255,6 +262,12 @@ class WebPluginImpl : public WebPlugin, bool windowless_; gfx::PluginWindowHandle window_; +#if defined(OS_MACOSX) + bool next_io_surface_allocated_; + int32 next_io_surface_width_; + int32 next_io_surface_height_; + uint32 next_io_surface_id_; +#endif bool accepts_input_events_; base::WeakPtr<WebPluginPageDelegate> page_delegate_; WebKit::WebFrame* webframe_; |