Chromium Code Reviews| 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]; |