Index: content/browser/compositor/browser_compositor_view_mac.mm |
diff --git a/content/browser/compositor/browser_compositor_view_mac.mm b/content/browser/compositor/browser_compositor_view_mac.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5ebeddd077511dd59c7cb0ad3199f0bb22c4d9b9 |
--- /dev/null |
+++ b/content/browser/compositor/browser_compositor_view_mac.mm |
@@ -0,0 +1,174 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/compositor/browser_compositor_view_mac.h" |
+ |
+#include "base/debug/trace_event.h" |
+#include "base/mac/scoped_cftyperef.h" |
+#include "content/browser/renderer_host/compositing_iosurface_context_mac.h" |
+#include "content/browser/renderer_host/compositing_iosurface_mac.h" |
+#include "content/browser/renderer_host/software_layer_mac.h" |
+#include "ui/base/cocoa/animation_utils.h" |
+#include "ui/gl/scoped_cgl.h" |
+ |
+// The default implementation of additions to the NSView interface for browser |
+// compositing should never be called. Log an error if they are. |
+@implementation NSView (BrowserCompositorView) |
+ |
+- (void)gotAcceleratedIOSurfaceFrame:(uint64)surface_handle |
+ withPixelSize:(gfx::Size)pixel_size |
+ withScaleFactor:(float)scale_factor { |
+ DLOG(ERROR) << "-[NSView gotAcceleratedIOSurfaceFrame] called on " |
+ << "non-overriden class."; |
+} |
+ |
+- (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data |
+ withScaleFactor:(float)scale_factor |
+ withCanvas:(SkCanvas*)canvas { |
+ DLOG(ERROR) << "-[NSView gotSoftwareFrame] called on non-overridden class."; |
+} |
+ |
+@end // NSView (BrowserCompositorView) |
+ |
+@implementation BrowserCompositorViewMac : NSView |
+ |
+- (id)initWithSuperview:(NSView*)view { |
+ if (self = [super init]) { |
+ // Disable the fade-in animation as the layer and view are added. |
+ ScopedCAActionDisabler disabler; |
+ |
+ // Make this view host a transparent layer. |
+ background_layer_.reset([[CALayer alloc] init]); |
+ [background_layer_ setContentsGravity:kCAGravityTopLeft]; |
+ [self setLayer:background_layer_]; |
+ [self setWantsLayer:YES]; |
+ |
+ compositor_.reset(new ui::Compositor(self)); |
+ [view addSubview:self]; |
+ } |
+ return self; |
+} |
+ |
+// This function closely mirrors RenderWidgetHostViewMac::LayoutLayers. When |
+// only delegated rendering is supported, only one copy of this code will |
+// need to exist. |
+- (void)layoutLayers { |
+ // Disable animation of the layers' resizing or repositioning. |
+ ScopedCAActionDisabler disabler; |
+ |
+ NSSize superview_frame_size = [[self superview] frame].size; |
+ [self setFrame:NSMakeRect( |
+ 0, 0, superview_frame_size.width, superview_frame_size.height)]; |
+ |
+ CGRect new_background_frame = CGRectMake( |
+ 0, |
+ 0, |
+ superview_frame_size.width, |
+ superview_frame_size.height); |
+ [background_layer_ setFrame:new_background_frame]; |
+ |
+ // The bounds of the accelerated layer determine the size of the GL surface |
+ // that will be drawn to. Make sure that this is big enough to draw the |
+ // IOSurface. |
+ if (accelerated_layer_) { |
+ CGRect layer_bounds = CGRectMake( |
+ 0, |
+ 0, |
+ [accelerated_layer_ iosurface]->dip_io_surface_size().width(), |
+ [accelerated_layer_ iosurface]->dip_io_surface_size().height()); |
+ CGPoint layer_position = CGPointMake( |
+ 0, |
+ CGRectGetHeight(new_background_frame) - CGRectGetHeight(layer_bounds)); |
+ bool bounds_changed = !CGRectEqualToRect( |
+ layer_bounds, [accelerated_layer_ bounds]); |
+ [accelerated_layer_ setBounds:layer_bounds]; |
+ [accelerated_layer_ setPosition:layer_position]; |
+ if (bounds_changed) { |
+ [accelerated_layer_ setNeedsDisplay]; |
+ [accelerated_layer_ displayIfNeeded]; |
+ } |
+ } |
+ |
+ // The content area of the software layer is the size of the image provided. |
+ // Make the bounds of the layer match the superview's bounds, to ensure that |
+ // the visible contents are drawn. |
+ [software_layer_ setBounds:new_background_frame]; |
+} |
+ |
+- (ui::Compositor*)compositor { |
+ return compositor_.get(); |
+} |
+ |
+- (void)gotAcceleratedIOSurfaceFrame:(uint64)surface_handle |
+ withPixelSize:(gfx::Size)pixel_size |
+ withScaleFactor:(float)scale_factor { |
+ ScopedCAActionDisabler disabler; |
+ |
+ // If there is not a layer for accelerated frames, create one. |
+ if (!accelerated_layer_) { |
+ // Disable the fade-in animation as the layer is added. |
+ ScopedCAActionDisabler disabler; |
+ scoped_refptr<content::CompositingIOSurfaceMac> iosurface = |
+ content::CompositingIOSurfaceMac::Create(); |
+ accelerated_layer_.reset([[CompositingIOSurfaceLayer alloc] |
+ initWithIOSurface:iosurface |
+ withClient:NULL]); |
+ [[self layer] addSublayer:accelerated_layer_]; |
+ } |
+ |
+ { |
+ bool result = true; |
+ gfx::ScopedCGLSetCurrentContext scoped_set_current_context( |
+ [accelerated_layer_ context]->cgl_context()); |
+ result = [accelerated_layer_ iosurface]->SetIOSurfaceWithContextCurrent( |
+ [accelerated_layer_ context], surface_handle, pixel_size, scale_factor); |
+ // TODO(ccameron): On failure, poison the GL context, tear down the layers, |
+ // and request a new frame. |
+ ignore_result(result); |
+ } |
+ [accelerated_layer_ gotNewFrame]; |
+ [self layoutLayers]; |
+ |
+ // If there was a software layer, remove it. |
+ if (software_layer_) { |
+ // Disable the fade-out animation as the layer is removed. |
+ ScopedCAActionDisabler disabler; |
+ [software_layer_ removeFromSuperlayer]; |
+ software_layer_.reset(); |
+ } |
+} |
+ |
+- (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data |
+ withScaleFactor:(float)scale_factor |
+ withCanvas:(SkCanvas*)canvas { |
+ if (!frame_data || !canvas) |
+ return; |
+ |
+ // If there is not a layer for software frames, create one. |
+ if (!software_layer_) { |
+ // Disable the fade-in animation as the layer is added. |
+ ScopedCAActionDisabler disabler; |
+ software_layer_.reset([[SoftwareLayer alloc] init]); |
+ [[self layer] addSublayer:software_layer_]; |
+ } |
+ |
+ SkImageInfo info; |
+ size_t row_bytes; |
+ const void* pixels = canvas->peekPixels(&info, &row_bytes); |
+ [software_layer_ setContentsToData:pixels |
+ withRowBytes:row_bytes |
+ withPixelSize:gfx::Size(info.fWidth, info.fHeight) |
+ withScaleFactor:scale_factor]; |
+ [self layoutLayers]; |
+ |
+ // If there was an accelerated layer, remove it. |
+ if (accelerated_layer_) { |
+ // Disable the fade-out animation as the layer is removed. |
+ ScopedCAActionDisabler disabler; |
+ [accelerated_layer_ removeFromSuperlayer]; |
+ accelerated_layer_.reset(); |
+ } |
+} |
+ |
+@end // BrowserCompositorViewMac |