summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-10 20:01:35 +0000
committerpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-10 20:01:35 +0000
commit3d1e89df95d421bcedec406019b3a9dbbf94b8c1 (patch)
tree2ed165930ca9f7520e94d49911a8245d54502478 /webkit
parentcb0ce1e02b7d16ab9024da9335ab7c70c493aa4e (diff)
downloadchromium_src-3d1e89df95d421bcedec406019b3a9dbbf94b8c1.zip
chromium_src-3d1e89df95d421bcedec406019b3a9dbbf94b8c1.tar.gz
chromium_src-3d1e89df95d421bcedec406019b3a9dbbf94b8c1.tar.bz2
Implement the CoreAnimation drawing model for plug-ins, sharing IPC and some rendering code with the GPU Plug-in. The drawing model negotiation is currently disabled so this should have no visible impact to plug-ins.
BUG=32012 TEST=make sure the pepper GPU plug-ins still work. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41194 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/plugins/plugin_host.cc42
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h39
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_mac.mm99
-rw-r--r--webkit/glue/webplugin.h20
-rw-r--r--webkit/tools/test_shell/mac/accelerated_surface_stub.cc49
-rw-r--r--webkit/tools/test_shell/test_shell.gypi1
-rw-r--r--webkit/webkit.gyp5
7 files changed, 240 insertions, 15 deletions
diff --git a/webkit/glue/plugins/plugin_host.cc b/webkit/glue/plugins/plugin_host.cc
index 0db965c..4cd5b3b 100644
--- a/webkit/glue/plugins/plugin_host.cc
+++ b/webkit/glue/plugins/plugin_host.cc
@@ -9,6 +9,9 @@
#include "base/scoped_ptr.h"
#include "base/string_piece.h"
#include "base/string_util.h"
+#if defined(OS_MACOSX)
+#include "base/sys_info.h"
+#endif
#include "base/sys_string_conversions.h"
#include "net/base/net_util.h"
#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
@@ -36,6 +39,21 @@ static NPAPI::PluginInstance* FindInstance(NPP id) {
return reinterpret_cast<NPAPI::PluginInstance*>(id->ndata);
}
+#if defined(OS_MACOSX)
+// Returns true if the OS supports shared accelerated surfaces via IOSurface.
+// This is true on Snow Leopard and higher.
+static bool SupportsSharingAcceleratedSurfaces() {
+ int32 major, minor, bugfix;
+ base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
+#if PINK_USE_COREANIMATION
+ // TODO(pinkerton): enable this, http://crbug.com/32012
+ return major > 10 || (major == 10 && minor > 5);
+#else
+ return false;
+#endif
+}
+#endif
+
namespace NPAPI {
scoped_refptr<PluginHost> PluginHost::singleton_;
@@ -757,7 +775,10 @@ NPError NPN_GetValue(NPP id, NPNVariable variable, void* value) {
}
#ifndef NP_NO_QUICKDRAW
case NPNVsupportsQuickDrawBool: {
- // we do not admit to supporting the QuickDraw drawing model.
+ // We do not admit to supporting the QuickDraw drawing model. The logic
+ // here is that our QuickDraw plugin support is so rudimentary that we
+ // only want to use it as a fallback to keep plugins from crashing: if a
+ // plugin knows enough to ask, we want them to use CoreGraphics.
NPBool* supports_qd = reinterpret_cast<NPBool*>(value);
*supports_qd = FALSE;
rv = NPERR_NO_ERROR;
@@ -775,9 +796,16 @@ NPError NPN_GetValue(NPP id, NPNVariable variable, void* value) {
rv = NPERR_NO_ERROR;
break;
}
- case NPNVsupportsOpenGLBool:
case NPNVsupportsCoreAnimationBool: {
- // we do not support these drawing and event models.
+ // We only support the Core Animation model on 10.6 and higher
+ NPBool* supports_model = reinterpret_cast<NPBool*>(value);
+ *supports_model = SupportsSharingAcceleratedSurfaces() ? TRUE : FALSE;
+ rv = NPERR_NO_ERROR;
+ break;
+ }
+ case NPNVsupportsOpenGLBool: {
+ // This drawing model was never widely supported, and we don't plan to
+ // support it.
NPBool* supports_model = reinterpret_cast<NPBool*>(value);
*supports_model = FALSE;
rv = NPERR_NO_ERROR;
@@ -838,14 +866,14 @@ NPError NPN_SetValue(NPP id, NPPVariable variable, void* value) {
return NPERR_GENERIC_ERROR;
#if defined(OS_MACOSX)
case NPPVpluginDrawingModel: {
- // We only admit to supporting the CoreGraphics drawing model. The logic
- // here is that our QuickDraw plugin support is so rudimentary that we
- // only want to use it as a fallback to keep plugins from crashing: if
- // a plugin knows enough to ask, we want them to use CoreGraphics.
int model = reinterpret_cast<int>(value);
if (model == NPDrawingModelCoreGraphics) {
plugin->set_drawing_model(model);
return NPERR_NO_ERROR;
+ } else if (model == NPDrawingModelCoreAnimation &&
+ SupportsSharingAcceleratedSurfaces()) {
+ plugin->set_drawing_model(model);
+ return NPERR_NO_ERROR;
}
return NPERR_GENERIC_ERROR;
}
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index 1327464..d8bb88c 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -16,10 +16,15 @@
#include "base/gfx/rect.h"
#include "base/ref_counted.h"
#include "base/task.h"
+#include "base/timer.h"
#include "third_party/npapi/bindings/npapi.h"
#include "webkit/glue/webcursor.h"
#include "webkit/glue/webplugin_delegate.h"
+#if defined(OS_MACOSX)
+#include "chrome/common/accelerated_surface_mac.h"
+#endif
+
#if defined(USE_X11)
typedef struct _GdkDrawable GdkPixmap;
#endif
@@ -32,8 +37,19 @@ namespace WebKit {
class WebMouseEvent;
}
-// An implementation of WebPluginDelegate that proxies all calls to
-// the plugin process.
+#if defined(OS_MACOSX)
+class CoreAnimationRedrawTimerSource;
+#ifdef __OBJC__
+@class CALayer;
+@class CARenderer;
+#else
+class CALayer;
+class CARenderer;
+#endif
+#endif
+
+// An implementation of WebPluginDelegate that runs in the plugin process,
+// proxied from the renderer by WebPluginDelegateProxy.
class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
public:
enum PluginQuirks {
@@ -146,6 +162,12 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
// Informs the delegate that the plugin set a Cocoa NSCursor.
void SetNSCursor(NSCursor* cursor);
+ // Informs the browser about the updated accelerated drawing surface.
+ void UpdateAcceleratedSurface();
+
+ // Uses a CARenderer to draw the plug-in's layer in our OpenGL surface.
+ void DrawLayerInSurface();
+
#ifndef NP_NO_CARBON
// Indicates that it's time to send the plugin a null event.
void FireIdleEvent();
@@ -157,10 +179,11 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
}
#if defined(OS_MACOSX)
- // On Mac OS X and for the GPU plugin only, this handle is a fake
- // one and comes in from the outside world.
+ // Allow setting a "fake" window handle to associate this plug-in with
+ // an IOSurface in the browser. Used for accelerated drawing surfaces.
void set_windowed_handle(gfx::PluginWindowHandle handle) {
windowed_handle_ = handle;
+ UpdateAcceleratedSurface();
}
#endif
@@ -244,7 +267,7 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
// used for windowed plugins
// Note: on Mac OS X, the only time the windowed handle is non-zero
- // is the case of the GPU plugin, which uses a fake window handle to
+ // is the case of accelerated rendering, which uses a fake window handle to
// identify itself back to the browser. It still performs all of its
// work offscreen.
gfx::PluginWindowHandle windowed_handle_;
@@ -301,6 +324,10 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
#ifndef NP_NO_QUICKDRAW
NP_Port qd_port_;
#endif
+ CALayer* layer_; // Used for CA drawing mode. Weak, retained by plug-in.
+ AcceleratedSurface* surface_;
+ CARenderer* renderer_; // Renders layer_ to surface_.
+ scoped_ptr<base::RepeatingTimer<WebPluginDelegateImpl> > redraw_timer_;
#endif
gfx::Rect window_rect_;
gfx::Rect clip_rect_;
@@ -356,7 +383,7 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate {
#ifndef NP_NO_CARBON
// Moves our dummy window to match the current screen location of the plugin.
void UpdateDummyWindowBounds(const gfx::Point& plugin_origin);
-
+
#ifndef NP_NO_QUICKDRAW
// Scrapes the contents of our dummy window into the given context.
void ScrapeDummyWindowIntoContext(CGContextRef context);
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
index 0a1e84e..0a2f963 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
+++ b/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#import <Cocoa/Cocoa.h>
+#import <QuartzCore/QuartzCore.h>
#include "webkit/glue/plugins/webplugin_delegate_impl.h"
@@ -16,7 +17,6 @@
#include "base/scoped_ptr.h"
#include "base/stats_counters.h"
#include "base/string_util.h"
-#include "base/timer.h"
#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
#include "webkit/default_plugin/plugin_impl.h"
#include "webkit/glue/webplugin.h"
@@ -49,6 +49,8 @@ using WebKit::WebInputEvent;
using WebKit::WebMouseEvent;
using WebKit::WebMouseWheelEvent;
+const int kCoreAnimationRedrawPeriodMs = 20; // 50fps
+
// Important implementation notes: The Mac definition of NPAPI, particularly
// the distinction between windowed and windowless modes, differs from the
// Windows and Linux definitions. Most of those differences are
@@ -169,16 +171,22 @@ class CarbonIdleEventSource {
} // namespace
+#pragma mark -
+
WebPluginDelegateImpl::WebPluginDelegateImpl(
gfx::PluginWindowHandle containing_view,
NPAPI::PluginInstance *instance)
- : windowless_needs_set_window_(true),
+ : windowed_handle_(NULL),
+ windowless_needs_set_window_(true),
// all Mac plugins are "windowless" in the Windows/X11 sense
windowless_(true),
plugin_(NULL),
instance_(instance),
parent_(containing_view),
buffer_context_(NULL),
+ layer_(nil),
+ surface_(NULL),
+ renderer_(nil),
quirks_(0),
have_focus_(false),
focus_notifier_(NULL),
@@ -256,6 +264,32 @@ void WebPluginDelegateImpl::PlatformInitialize() {
#endif
window_.type = NPWindowTypeDrawable;
break;
+ case NPDrawingModelCoreAnimation: { // Assumes Cocoa event model.
+ window_.type = NPWindowTypeDrawable;
+ // Ask the plug-in for the CALayer it created for rendering content. Have
+ // the renderer tell the browser to create a "windowed plugin" to host
+ // the IOSurface. The surface itself will be created when the plug-in
+ // is sized.
+ CALayer* layer = nil;
+ NPError err = instance()->NPP_GetValue(NPPVpluginCoreAnimationLayer,
+ reinterpret_cast<void*>(&layer));
+ if (!err) {
+ layer_ = layer;
+ plugin_->BindFakePluginWindowHandle();
+ surface_ = new AcceleratedSurface;
+ surface_->Initialize();
+ UpdateAcceleratedSurface();
+ renderer_ = [[CARenderer rendererWithCGLContext:surface_->context()
+ options:NULL] retain];
+ [renderer_ setLayer:layer_];
+ redraw_timer_.reset(new base::RepeatingTimer<WebPluginDelegateImpl>);
+ redraw_timer_->Start(
+ base::TimeDelta::FromMilliseconds(kCoreAnimationRedrawPeriodMs),
+ this,
+ &WebPluginDelegateImpl::DrawLayerInSurface);
+ }
+ break;
+ }
default:
NOTREACHED();
break;
@@ -286,6 +320,16 @@ void WebPluginDelegateImpl::PlatformDestroyInstance() {
if (instance()->event_model() == NPEventModelCarbon)
CarbonIdleEventSource::SharedInstance()->UnregisterDelegate(this);
#endif
+ if (redraw_timer_.get())
+ redraw_timer_->Stop();
+ [renderer_ release];
+ renderer_ = nil;
+ layer_ = nil;
+ if (surface_) {
+ surface_->Destroy();
+ delete surface_;
+ surface_ = NULL;
+ }
}
void WebPluginDelegateImpl::UpdateGeometryAndContext(
@@ -379,8 +423,32 @@ void WebPluginDelegateImpl::WindowlessUpdateGeometry(
WindowlessSetWindow(true);
}
+void WebPluginDelegateImpl::DrawLayerInSurface() {
+ surface_->MakeCurrent();
+
+ surface_->Clear(window_rect_);
+
+ // Ensure all changes are made before rendering. Not sure where the |-begin|
+ // comes from, but not doing this causes nothing to render.
+ [CATransaction commit];
+ [renderer_ beginFrameAtTime:CACurrentMediaTime() timeStamp:NULL];
+ CGRect layerRect = [layer_ bounds];
+ [renderer_ addUpdateRect:layerRect];
+ [renderer_ render];
+ [renderer_ endFrame];
+
+ surface_->SwapBuffers();
+ plugin_->AcceleratedFrameBuffersDidSwap(windowed_handle());
+}
+
void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
const gfx::Rect& damage_rect) {
+ // There is currently nothing to do for the Core Animation drawing model,
+ // but there have been discussions on the plugin-futures mailing list that
+ // might require future work.
+ if (instance()->drawing_model() == NPDrawingModelCoreAnimation)
+ return;
+
// If we somehow get a paint before we've set up the plugin buffer, bail.
if (!buffer_context_)
return;
@@ -458,6 +526,8 @@ void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) {
SetWindowHasFocus(initial_window_focus_);
}
+ UpdateAcceleratedSurface();
+
DCHECK(err == NPERR_NO_ERROR);
}
@@ -580,6 +650,30 @@ void WebPluginDelegateImpl::SetContainerVisibility(bool is_visible) {
}
}
+// Generate an IOSurface for accelerated drawing (but only in the case where a
+// window handle has been set). Once the surface has been updated for the
+// current size of the plug-in, tell the browser host view so it can adjust its
+// bookkeeping and CALayer appropriately.
+void WebPluginDelegateImpl::UpdateAcceleratedSurface() {
+ // Will only have a window handle when using the CoreAnimation drawing model.
+ if (!windowed_handle() ||
+ instance()->drawing_model() != NPDrawingModelCoreAnimation)
+ return;
+
+ [layer_ setFrame:CGRectMake(0, 0,
+ window_rect_.width(), window_rect_.height())];
+ [renderer_ setBounds:[layer_ bounds]];
+
+ uint64 io_surface_id = surface_->SetSurfaceSize(window_rect_.width(),
+ window_rect_.height());
+ if (io_surface_id) {
+ plugin_->SetAcceleratedSurface(windowed_handle(),
+ window_rect_.width(),
+ window_rect_.height(),
+ io_surface_id);
+ }
+}
+
void WebPluginDelegateImpl::WindowFrameChanged(gfx::Rect window_frame,
gfx::Rect view_frame) {
instance()->set_window_frame(window_frame);
@@ -600,6 +694,7 @@ void WebPluginDelegateImpl::SetNSCursor(NSCursor* cursor) {
void WebPluginDelegateImpl::SetPluginRect(const gfx::Rect& rect) {
window_rect_ = rect;
+ UpdateAcceleratedSurface();
PluginScreenLocationChanged();
}
diff --git a/webkit/glue/webplugin.h b/webkit/glue/webplugin.h
index d83601a..3f9c7e5 100644
--- a/webkit/glue/webplugin.h
+++ b/webkit/glue/webplugin.h
@@ -144,6 +144,26 @@ class WebPlugin {
virtual void SetDeferResourceLoading(unsigned long resource_id,
bool defer) = 0;
+#if defined(OS_MACOSX)
+ // Synthesize a fake window handle for the plug-in to identify the instance
+ // to the browser, allowing mapping to a surface for hardware accelleration
+ // of plug-in content. The browser generates the handle which is then set on
+ // the plug-in.
+ virtual void BindFakePluginWindowHandle() {}
+
+ // Tell the browser (via the renderer) to invalidate because the
+ // accelerated buffers have changed.
+ virtual void AcceleratedFrameBuffersDidSwap(gfx::PluginWindowHandle window) {}
+
+ // Tell the renderer and browser to associate the given plugin handle with
+ // |accelerated_surface_identifier|. The geometry is used to resize any
+ // native "window" (which on the Mac is a CALayer).
+ virtual void SetAcceleratedSurface(gfx::PluginWindowHandle window,
+ int32 width,
+ int32 height,
+ uint64 accelerated_surface_identifier) {}
+#endif
+
// Gets the WebPluginDelegate that implements the interface.
// This API is only for use with Pepper, and is only overridden
// by in-renderer implementations.
diff --git a/webkit/tools/test_shell/mac/accelerated_surface_stub.cc b/webkit/tools/test_shell/mac/accelerated_surface_stub.cc
new file mode 100644
index 0000000..f331a41
--- /dev/null
+++ b/webkit/tools/test_shell/mac/accelerated_surface_stub.cc
@@ -0,0 +1,49 @@
+// 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.
+
+// This file is a complete and total hack intended to stub out some classes
+// used by WebPluginDelegateImpl on Mac. Unfortunately, they live in
+// chrome/common, so we can't compile them into TestShell. Instead, provide
+// some stubs. It will need to be updated if new methods are added to
+// AcceleratedSurface that get called from WebPluginDelegateImpl. It's not
+// like plug-ins work in TestShell anyway.
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <OpenGL/OpenGL.h>
+
+#include "base/basictypes.h"
+#include "base/gfx/rect.h"
+#include "base/scoped_ptr.h"
+
+class TransportDIB {
+ public:
+ TransportDIB() { }
+ ~TransportDIB() { }
+};
+
+class AcceleratedSurface {
+ public:
+ AcceleratedSurface();
+ virtual ~AcceleratedSurface();
+
+ bool Initialize();
+ void Destroy();
+ uint64 SetSurfaceSize(int32 width, int32 height);
+ bool MakeCurrent();
+ void Clear(const gfx::Rect& rect);
+ void SwapBuffers();
+ CGLContextObj context() { return NULL; }
+ private:
+ scoped_ptr<TransportDIB> ignore_;
+};
+
+AcceleratedSurface::AcceleratedSurface() { }
+AcceleratedSurface::~AcceleratedSurface() { }
+bool AcceleratedSurface::Initialize() { return false; }
+void AcceleratedSurface::Destroy() { }
+uint64 AcceleratedSurface::SetSurfaceSize(int32 width, int32 height)
+ { return 0; }
+bool AcceleratedSurface::MakeCurrent() { return false; }
+void AcceleratedSurface::Clear(const gfx::Rect& rect) { }
+void AcceleratedSurface::SwapBuffers() { }
diff --git a/webkit/tools/test_shell/test_shell.gypi b/webkit/tools/test_shell/test_shell.gypi
index a28daf2..a1bd3cb 100644
--- a/webkit/tools/test_shell/test_shell.gypi
+++ b/webkit/tools/test_shell/test_shell.gypi
@@ -48,6 +48,7 @@
],
'msvs_guid': '77C32787-1B96-CB84-B905-7F170629F0AC',
'sources': [
+ 'mac/accelerated_surface_stub.cc',
'mac/DumpRenderTreePasteboard.h',
'mac/DumpRenderTreePasteboard.m',
'mac/test_shell_webview.h',
diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp
index 282bb3b..0754c9f 100644
--- a/webkit/webkit.gyp
+++ b/webkit/webkit.gyp
@@ -408,6 +408,11 @@
['exclude', r'/mac_']],
}, { # else: OS=="mac"
'sources/': [['exclude', 'plugin_(lib|list)_posix\\.cc$']],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/QuartzCore.framework',
+ ],
+ },
}],
['enable_gpu==1', {
'dependencies': [