Index: chrome/browser/renderer_host/render_widget_host_view_mac.mm |
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm |
index 4a634b2b2c32afd7dbd6bbf49cfce77f2ccf6c31..37bd963d564fb9fe8c084560f789dd7e1d7bc3e1 100644 |
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm |
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm |
@@ -135,6 +135,13 @@ void DisablePasswordInput() { |
// This subclass of NSView hosts the output of accelerated plugins on |
// the page. |
+// Informat protocol implemented by windows that need to be informed explicitly |
+// about underlay surfaces. |
+@protocol UnderlayableSurface |
pink (ping after 24hrs)
2010/08/24 17:18:55
If it's a @protocol, then it's formal. s/Informal/
Nico
2010/08/24 17:27:55
Not really, since nothing implements this protocol
|
+- (void)underlaySurfaceAdded; |
+- (void)underlaySurfaceRemoved; |
+@end |
+ |
@interface AcceleratedPluginView : NSView { |
scoped_nsobject<NSOpenGLPixelFormat> glPixelFormat_; |
CGLPixelFormatObj cglPixelFormat_; // weak, backed by |glPixelFormat_|. |
@@ -148,10 +155,15 @@ void DisablePasswordInput() { |
// True if the backing IO surface was updated since we last painted. |
BOOL surfaceWasSwapped_; |
+ |
+ // True if the surface might contain transparent pixels that need to be |
+ // blended. |
+ BOOL canDrawTransparent_; |
} |
- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r |
- pluginHandle:(gfx::PluginWindowHandle)pluginHandle; |
+ pluginHandle:(gfx::PluginWindowHandle)pluginHandle |
+ canDrawTransparent:(BOOL)canDrawTransparent; |
- (void)drawView; |
// This _must_ be atomic, since it's accessed from several threads. |
@@ -187,11 +199,30 @@ static CVReturn DrawOneAcceleratedPluginCallback( |
return result; |
} |
+- (BOOL)drawAsUnderlaySurface { |
+ // Transparent plugins really need to be handled by the GPU process. Until |
+ // then, we have the coice of two evils: |
pink (ping after 24hrs)
2010/08/24 17:18:55
choice
Nico
2010/08/24 17:27:55
will fix when i touch this file again (probably so
|
+ // 1.) They are drawn as underlay surface, blending with whatever is behind |
+ // the browser window (instead of blending with the webpage as intended) |
+ // 2.) They are blended with the web page but drawn on top of sibling windows |
+ // such as the find bar and the fullscreen window overlay. |
+ // Option 2 seems less bad, so don't show transparent plugins as underlays. |
+ // |
+ // Note that this never happens in practice at the moment, because |
+ // |canDrawTransparent| will only be true for flash with wmode=transparent and |
+ // sliverlight with a transparent background, and these don't use |
+ // CoreAnimation when they're transparent. |
+ return !canDrawTransparent_ && !CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kDisableHolePunching); |
+} |
+ |
- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r |
- pluginHandle:(gfx::PluginWindowHandle)pluginHandle { |
+ pluginHandle:(gfx::PluginWindowHandle)pluginHandle |
+ canDrawTransparent:(BOOL)canDrawTransparent { |
if ((self = [super initWithFrame:NSZeroRect])) { |
renderWidgetHostView_ = r; |
pluginHandle_ = pluginHandle; |
+ canDrawTransparent_ = canDrawTransparent; |
[self setAutoresizingMask:NSViewMaxXMargin|NSViewMinYMargin]; |
@@ -203,6 +234,13 @@ static CVReturn DrawOneAcceleratedPluginCallback( |
glContext_.reset([[NSOpenGLContext alloc] initWithFormat:glPixelFormat_ |
shareContext:nil]); |
+ if ([self drawAsUnderlaySurface]) { |
+ // We "punch a hole" in the window, and have the WindowServer render the |
+ // OpenGL surface underneath so we can draw over it. |
+ GLint belowWindow = -1; |
+ [glContext_ setValues:&belowWindow forParameter:NSOpenGLCPSurfaceOrder]; |
+ } |
+ |
cglContext_ = (CGLContextObj)[glContext_ CGLContextObj]; |
cglPixelFormat_ = (CGLPixelFormatObj)[glPixelFormat_ CGLPixelFormatObj]; |
@@ -210,7 +248,6 @@ static CVReturn DrawOneAcceleratedPluginCallback( |
GLint swapInterval = 1; |
[glContext_ setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; |
- |
// Set up a display link to do OpenGL rendering on a background thread. |
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink_); |
CVDisplayLinkSetOutputCallback(displayLink_, |
@@ -234,6 +271,16 @@ static CVReturn DrawOneAcceleratedPluginCallback( |
} |
- (void)drawRect:(NSRect)rect { |
+ if ([self drawAsUnderlaySurface]) { |
+ const NSRect* dirtyRects; |
+ int dirtyRectCount; |
+ |
+ [self getRectsBeingDrawn:&dirtyRects count:&dirtyRectCount]; |
+ // Punch a hole so that the OpenGL view shows through. |
+ [[NSColor clearColor] set]; |
+ NSRectFillList(dirtyRects, dirtyRectCount); |
+ } |
+ |
[self drawView]; |
} |
@@ -287,6 +334,22 @@ static CVReturn DrawOneAcceleratedPluginCallback( |
[[NSNotificationCenter defaultCenter] removeObserver:self]; |
[super dealloc]; |
} |
+ |
+- (void)viewWillMoveToWindow:(NSWindow*)newWindow { |
+ if (![self drawAsUnderlaySurface]) { |
+ return; |
+ } |
+ |
+ if ([self window] && |
pink (ping after 24hrs)
2010/08/24 17:18:55
do you need the extra window null checks? [nil res
Nico
2010/08/24 17:27:55
i don't need them, but i thought it's clearer.
si
|
+ [[self window] respondsToSelector:@selector(underlaySurfaceRemoved)]) { |
+ [static_cast<id>([self window]) underlaySurfaceRemoved]; |
+ } |
+ |
+ if (newWindow && |
+ [newWindow respondsToSelector:@selector(underlaySurfaceAdded)]) { |
+ [static_cast<id>(newWindow) underlaySurfaceAdded]; |
+ } |
+} |
@end |
// RenderWidgetHostView -------------------------------------------------------- |
@@ -763,16 +826,16 @@ void RenderWidgetHostViewMac::KillSelf() { |
} |
} |
-gfx::PluginWindowHandle |
-RenderWidgetHostViewMac::AllocateFakePluginWindowHandle(bool opaque, |
- bool root) { |
+gfx::PluginWindowHandle RenderWidgetHostViewMac::AllocateFakePluginWindowHandle( |
+ bool opaque, bool can_draw_transparent, bool root) { |
// Create an NSView to host the plugin's/compositor's pixels. |
gfx::PluginWindowHandle handle = |
plugin_container_manager_.AllocateFakePluginWindowHandle(opaque, root); |
- scoped_nsobject<NSView> plugin_view( |
- [[AcceleratedPluginView alloc] initWithRenderWidgetHostViewMac:this |
- pluginHandle:handle]); |
+ scoped_nsobject<NSView> plugin_view([[AcceleratedPluginView alloc] |
+ initWithRenderWidgetHostViewMac:this |
+ pluginHandle:handle |
+ canDrawTransparent:can_draw_transparent]); |
[plugin_view setHidden:YES]; |
[cocoa_view_ addSubview:plugin_view]; |