Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: chrome/browser/renderer_host/render_widget_host_view_mac.mm

Issue 3176027: Mac: Well-behaved accelerated plugins, actual fix (Closed)
Patch Set: test Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_mac.h ('k') | chrome/browser/renderer_host/test/test_render_view_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698