OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <QuartzCore/QuartzCore.h> | 5 #include <QuartzCore/QuartzCore.h> |
6 | 6 |
7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" | 7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" |
8 | 8 |
9 #include "app/surface/io_surface_support_mac.h" | 9 #include "app/surface/io_surface_support_mac.h" |
10 #import "base/chrome_application_mac.h" | 10 #import "base/chrome_application_mac.h" |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 TSMRemoveDocumentProperty(0, kTSMDocumentEnabledInputSourcesPropertyTag); | 128 TSMRemoveDocumentProperty(0, kTSMDocumentEnabledInputSourcesPropertyTag); |
129 } | 129 } |
130 | 130 |
131 } // namespace | 131 } // namespace |
132 | 132 |
133 // AcceleratedPluginView ------------------------------------------------------ | 133 // AcceleratedPluginView ------------------------------------------------------ |
134 | 134 |
135 // This subclass of NSView hosts the output of accelerated plugins on | 135 // This subclass of NSView hosts the output of accelerated plugins on |
136 // the page. | 136 // the page. |
137 | 137 |
138 // Informat protocol implemented by windows that need to be informed explicitly | |
139 // about underlay surfaces. | |
140 @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
| |
141 - (void)underlaySurfaceAdded; | |
142 - (void)underlaySurfaceRemoved; | |
143 @end | |
144 | |
138 @interface AcceleratedPluginView : NSView { | 145 @interface AcceleratedPluginView : NSView { |
139 scoped_nsobject<NSOpenGLPixelFormat> glPixelFormat_; | 146 scoped_nsobject<NSOpenGLPixelFormat> glPixelFormat_; |
140 CGLPixelFormatObj cglPixelFormat_; // weak, backed by |glPixelFormat_|. | 147 CGLPixelFormatObj cglPixelFormat_; // weak, backed by |glPixelFormat_|. |
141 scoped_nsobject<NSOpenGLContext> glContext_; | 148 scoped_nsobject<NSOpenGLContext> glContext_; |
142 CGLContextObj cglContext_; // weak, backed by |glContext_|. | 149 CGLContextObj cglContext_; // weak, backed by |glContext_|. |
143 | 150 |
144 CVDisplayLinkRef displayLink_; // Owned by us. | 151 CVDisplayLinkRef displayLink_; // Owned by us. |
145 | 152 |
146 RenderWidgetHostViewMac* renderWidgetHostView_; // weak | 153 RenderWidgetHostViewMac* renderWidgetHostView_; // weak |
147 gfx::PluginWindowHandle pluginHandle_; // weak | 154 gfx::PluginWindowHandle pluginHandle_; // weak |
148 | 155 |
149 // True if the backing IO surface was updated since we last painted. | 156 // True if the backing IO surface was updated since we last painted. |
150 BOOL surfaceWasSwapped_; | 157 BOOL surfaceWasSwapped_; |
158 | |
159 // True if the surface might contain transparent pixels that need to be | |
160 // blended. | |
161 BOOL canDrawTransparent_; | |
151 } | 162 } |
152 | 163 |
153 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r | 164 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r |
154 pluginHandle:(gfx::PluginWindowHandle)pluginHandle; | 165 pluginHandle:(gfx::PluginWindowHandle)pluginHandle |
166 canDrawTransparent:(BOOL)canDrawTransparent; | |
155 - (void)drawView; | 167 - (void)drawView; |
156 | 168 |
157 // This _must_ be atomic, since it's accessed from several threads. | 169 // This _must_ be atomic, since it's accessed from several threads. |
158 @property BOOL surfaceWasSwapped; | 170 @property BOOL surfaceWasSwapped; |
159 @end | 171 @end |
160 | 172 |
161 @implementation AcceleratedPluginView : NSView | 173 @implementation AcceleratedPluginView : NSView |
162 @synthesize surfaceWasSwapped = surfaceWasSwapped_; | 174 @synthesize surfaceWasSwapped = surfaceWasSwapped_; |
163 | 175 |
164 - (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime { | 176 - (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime { |
(...skipping 15 matching lines...) Expand all Loading... | |
180 const CVTimeStamp* now, | 192 const CVTimeStamp* now, |
181 const CVTimeStamp* outputTime, | 193 const CVTimeStamp* outputTime, |
182 CVOptionFlags flagsIn, | 194 CVOptionFlags flagsIn, |
183 CVOptionFlags* flagsOut, | 195 CVOptionFlags* flagsOut, |
184 void* displayLinkContext) { | 196 void* displayLinkContext) { |
185 CVReturn result = | 197 CVReturn result = |
186 [(AcceleratedPluginView*)displayLinkContext getFrameForTime:outputTime]; | 198 [(AcceleratedPluginView*)displayLinkContext getFrameForTime:outputTime]; |
187 return result; | 199 return result; |
188 } | 200 } |
189 | 201 |
202 - (BOOL)drawAsUnderlaySurface { | |
203 // Transparent plugins really need to be handled by the GPU process. Until | |
204 // 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
| |
205 // 1.) They are drawn as underlay surface, blending with whatever is behind | |
206 // the browser window (instead of blending with the webpage as intended) | |
207 // 2.) They are blended with the web page but drawn on top of sibling windows | |
208 // such as the find bar and the fullscreen window overlay. | |
209 // Option 2 seems less bad, so don't show transparent plugins as underlays. | |
210 // | |
211 // Note that this never happens in practice at the moment, because | |
212 // |canDrawTransparent| will only be true for flash with wmode=transparent and | |
213 // sliverlight with a transparent background, and these don't use | |
214 // CoreAnimation when they're transparent. | |
215 return !canDrawTransparent_ && !CommandLine::ForCurrentProcess()->HasSwitch( | |
216 switches::kDisableHolePunching); | |
217 } | |
218 | |
190 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r | 219 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r |
191 pluginHandle:(gfx::PluginWindowHandle)pluginHandle { | 220 pluginHandle:(gfx::PluginWindowHandle)pluginHandle |
221 canDrawTransparent:(BOOL)canDrawTransparent { | |
192 if ((self = [super initWithFrame:NSZeroRect])) { | 222 if ((self = [super initWithFrame:NSZeroRect])) { |
193 renderWidgetHostView_ = r; | 223 renderWidgetHostView_ = r; |
194 pluginHandle_ = pluginHandle; | 224 pluginHandle_ = pluginHandle; |
225 canDrawTransparent_ = canDrawTransparent; | |
195 | 226 |
196 [self setAutoresizingMask:NSViewMaxXMargin|NSViewMinYMargin]; | 227 [self setAutoresizingMask:NSViewMaxXMargin|NSViewMinYMargin]; |
197 | 228 |
198 NSOpenGLPixelFormatAttribute attributes[] = | 229 NSOpenGLPixelFormatAttribute attributes[] = |
199 { NSOpenGLPFAAccelerated, NSOpenGLPFADoubleBuffer, 0}; | 230 { NSOpenGLPFAAccelerated, NSOpenGLPFADoubleBuffer, 0}; |
200 | 231 |
201 glPixelFormat_.reset([[NSOpenGLPixelFormat alloc] | 232 glPixelFormat_.reset([[NSOpenGLPixelFormat alloc] |
202 initWithAttributes:attributes]); | 233 initWithAttributes:attributes]); |
203 glContext_.reset([[NSOpenGLContext alloc] initWithFormat:glPixelFormat_ | 234 glContext_.reset([[NSOpenGLContext alloc] initWithFormat:glPixelFormat_ |
204 shareContext:nil]); | 235 shareContext:nil]); |
205 | 236 |
237 if ([self drawAsUnderlaySurface]) { | |
238 // We "punch a hole" in the window, and have the WindowServer render the | |
239 // OpenGL surface underneath so we can draw over it. | |
240 GLint belowWindow = -1; | |
241 [glContext_ setValues:&belowWindow forParameter:NSOpenGLCPSurfaceOrder]; | |
242 } | |
243 | |
206 cglContext_ = (CGLContextObj)[glContext_ CGLContextObj]; | 244 cglContext_ = (CGLContextObj)[glContext_ CGLContextObj]; |
207 cglPixelFormat_ = (CGLPixelFormatObj)[glPixelFormat_ CGLPixelFormatObj]; | 245 cglPixelFormat_ = (CGLPixelFormatObj)[glPixelFormat_ CGLPixelFormatObj]; |
208 | 246 |
209 // Draw at beam vsync. | 247 // Draw at beam vsync. |
210 GLint swapInterval = 1; | 248 GLint swapInterval = 1; |
211 [glContext_ setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; | 249 [glContext_ setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; |
212 | 250 |
213 | |
214 // Set up a display link to do OpenGL rendering on a background thread. | 251 // Set up a display link to do OpenGL rendering on a background thread. |
215 CVDisplayLinkCreateWithActiveCGDisplays(&displayLink_); | 252 CVDisplayLinkCreateWithActiveCGDisplays(&displayLink_); |
216 CVDisplayLinkSetOutputCallback(displayLink_, | 253 CVDisplayLinkSetOutputCallback(displayLink_, |
217 &DrawOneAcceleratedPluginCallback, self); | 254 &DrawOneAcceleratedPluginCallback, self); |
218 CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext( | 255 CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext( |
219 displayLink_, cglContext_, cglPixelFormat_); | 256 displayLink_, cglContext_, cglPixelFormat_); |
220 CVDisplayLinkStart(displayLink_); | 257 CVDisplayLinkStart(displayLink_); |
221 } | 258 } |
222 return self; | 259 return self; |
223 } | 260 } |
224 | 261 |
225 - (void)drawView { | 262 - (void)drawView { |
226 // Called on a background thread. Synchronized via the CGL context lock. | 263 // Called on a background thread. Synchronized via the CGL context lock. |
227 CGLLockContext(cglContext_); | 264 CGLLockContext(cglContext_); |
228 | 265 |
229 renderWidgetHostView_->DrawAcceleratedSurfaceInstance( | 266 renderWidgetHostView_->DrawAcceleratedSurfaceInstance( |
230 cglContext_, pluginHandle_); | 267 cglContext_, pluginHandle_); |
231 | 268 |
232 CGLFlushDrawable(cglContext_); | 269 CGLFlushDrawable(cglContext_); |
233 CGLUnlockContext(cglContext_); | 270 CGLUnlockContext(cglContext_); |
234 } | 271 } |
235 | 272 |
236 - (void)drawRect:(NSRect)rect { | 273 - (void)drawRect:(NSRect)rect { |
274 if ([self drawAsUnderlaySurface]) { | |
275 const NSRect* dirtyRects; | |
276 int dirtyRectCount; | |
277 | |
278 [self getRectsBeingDrawn:&dirtyRects count:&dirtyRectCount]; | |
279 // Punch a hole so that the OpenGL view shows through. | |
280 [[NSColor clearColor] set]; | |
281 NSRectFillList(dirtyRects, dirtyRectCount); | |
282 } | |
283 | |
237 [self drawView]; | 284 [self drawView]; |
238 } | 285 } |
239 | 286 |
240 - (void)rightMouseDown:(NSEvent*)event { | 287 - (void)rightMouseDown:(NSEvent*)event { |
241 // The NSResponder documentation: "Note: The NSView implementation of this | 288 // The NSResponder documentation: "Note: The NSView implementation of this |
242 // method does not pass the message up the responder chain, it handles it | 289 // method does not pass the message up the responder chain, it handles it |
243 // directly." | 290 // directly." |
244 // That's bad, we want the next responder (RWHVMac) to handle this event to | 291 // That's bad, we want the next responder (RWHVMac) to handle this event to |
245 // dispatch it to the renderer. | 292 // dispatch it to the renderer. |
246 [[self nextResponder] rightMouseDown:event]; | 293 [[self nextResponder] rightMouseDown:event]; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
280 object:self]; | 327 object:self]; |
281 } | 328 } |
282 [glContext_ makeCurrentContext]; | 329 [glContext_ makeCurrentContext]; |
283 } | 330 } |
284 | 331 |
285 - (void)dealloc { | 332 - (void)dealloc { |
286 CVDisplayLinkRelease(displayLink_); | 333 CVDisplayLinkRelease(displayLink_); |
287 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 334 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
288 [super dealloc]; | 335 [super dealloc]; |
289 } | 336 } |
337 | |
338 - (void)viewWillMoveToWindow:(NSWindow*)newWindow { | |
339 if (![self drawAsUnderlaySurface]) { | |
340 return; | |
341 } | |
342 | |
343 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
| |
344 [[self window] respondsToSelector:@selector(underlaySurfaceRemoved)]) { | |
345 [static_cast<id>([self window]) underlaySurfaceRemoved]; | |
346 } | |
347 | |
348 if (newWindow && | |
349 [newWindow respondsToSelector:@selector(underlaySurfaceAdded)]) { | |
350 [static_cast<id>(newWindow) underlaySurfaceAdded]; | |
351 } | |
352 } | |
290 @end | 353 @end |
291 | 354 |
292 // RenderWidgetHostView -------------------------------------------------------- | 355 // RenderWidgetHostView -------------------------------------------------------- |
293 | 356 |
294 // static | 357 // static |
295 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget( | 358 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget( |
296 RenderWidgetHost* widget) { | 359 RenderWidgetHost* widget) { |
297 return new RenderWidgetHostViewMac(widget); | 360 return new RenderWidgetHostViewMac(widget); |
298 } | 361 } |
299 | 362 |
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
756 | 819 |
757 void RenderWidgetHostViewMac::KillSelf() { | 820 void RenderWidgetHostViewMac::KillSelf() { |
758 if (shutdown_factory_.empty()) { | 821 if (shutdown_factory_.empty()) { |
759 [cocoa_view_ setHidden:YES]; | 822 [cocoa_view_ setHidden:YES]; |
760 MessageLoop::current()->PostTask(FROM_HERE, | 823 MessageLoop::current()->PostTask(FROM_HERE, |
761 shutdown_factory_.NewRunnableMethod( | 824 shutdown_factory_.NewRunnableMethod( |
762 &RenderWidgetHostViewMac::ShutdownHost)); | 825 &RenderWidgetHostViewMac::ShutdownHost)); |
763 } | 826 } |
764 } | 827 } |
765 | 828 |
766 gfx::PluginWindowHandle | 829 gfx::PluginWindowHandle RenderWidgetHostViewMac::AllocateFakePluginWindowHandle( |
767 RenderWidgetHostViewMac::AllocateFakePluginWindowHandle(bool opaque, | 830 bool opaque, bool can_draw_transparent, bool root) { |
768 bool root) { | |
769 // Create an NSView to host the plugin's/compositor's pixels. | 831 // Create an NSView to host the plugin's/compositor's pixels. |
770 gfx::PluginWindowHandle handle = | 832 gfx::PluginWindowHandle handle = |
771 plugin_container_manager_.AllocateFakePluginWindowHandle(opaque, root); | 833 plugin_container_manager_.AllocateFakePluginWindowHandle(opaque, root); |
772 | 834 |
773 scoped_nsobject<NSView> plugin_view( | 835 scoped_nsobject<NSView> plugin_view([[AcceleratedPluginView alloc] |
774 [[AcceleratedPluginView alloc] initWithRenderWidgetHostViewMac:this | 836 initWithRenderWidgetHostViewMac:this |
775 pluginHandle:handle]); | 837 pluginHandle:handle |
838 canDrawTransparent:can_draw_transparent]); | |
776 [plugin_view setHidden:YES]; | 839 [plugin_view setHidden:YES]; |
777 | 840 |
778 [cocoa_view_ addSubview:plugin_view]; | 841 [cocoa_view_ addSubview:plugin_view]; |
779 plugin_views_[handle] = plugin_view; | 842 plugin_views_[handle] = plugin_view; |
780 | 843 |
781 return handle; | 844 return handle; |
782 } | 845 } |
783 | 846 |
784 void RenderWidgetHostViewMac::DestroyFakePluginWindowHandle( | 847 void RenderWidgetHostViewMac::DestroyFakePluginWindowHandle( |
785 gfx::PluginWindowHandle window) { | 848 gfx::PluginWindowHandle window) { |
(...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2300 NSArray* toDeclare = [NSArray arrayWithObject:NSStringPboardType]; | 2363 NSArray* toDeclare = [NSArray arrayWithObject:NSStringPboardType]; |
2301 [pboard declareTypes:toDeclare owner:nil]; | 2364 [pboard declareTypes:toDeclare owner:nil]; |
2302 return [pboard setString:text forType:NSStringPboardType]; | 2365 return [pboard setString:text forType:NSStringPboardType]; |
2303 } | 2366 } |
2304 | 2367 |
2305 - (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard { | 2368 - (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard { |
2306 return NO; | 2369 return NO; |
2307 } | 2370 } |
2308 | 2371 |
2309 @end | 2372 @end |
OLD | NEW |