diff options
Diffstat (limited to 'webkit/glue/plugins/webplugin_delegate_impl_mac.mm')
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_mac.mm | 99 |
1 files changed, 97 insertions, 2 deletions
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(); } |