summaryrefslogtreecommitdiffstats
path: root/webkit/glue/plugins/webplugin_delegate_impl_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/glue/plugins/webplugin_delegate_impl_mac.mm')
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl_mac.mm99
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();
}