1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/compositor/browser_compositor_view_mac.h"
7 #include "base/debug/trace_event.h"
8 #include "base/mac/scoped_cftyperef.h"
9 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h"
10 #include "content/browser/renderer_host/compositing_iosurface_mac.h"
11 #include "content/browser/renderer_host/software_layer_mac.h"
12 #include "ui/base/cocoa/animation_utils.h"
13 #include "ui/gl/scoped_cgl.h"
15 // The default implementation of additions to the NSView interface for browser
16 // compositing should never be called. Log an error if they are.
17 @implementation NSView (BrowserCompositorView)
19 - (void)gotAcceleratedIOSurfaceFrame:(uint64)surface_handle
20 withPixelSize:(gfx::Size)pixel_size
21 withScaleFactor:(float)scale_factor {
22 DLOG(ERROR) << "-[NSView gotAcceleratedIOSurfaceFrame] called on "
23 << "non-overriden class.";
26 - (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data
27 withScaleFactor:(float)scale_factor
28 withCanvas:(SkCanvas*)canvas {
29 DLOG(ERROR) << "-[NSView gotSoftwareFrame] called on non-overridden class.";
32 @end // NSView (BrowserCompositorView)
34 @implementation BrowserCompositorViewMac : NSView
36 - (id)initWithSuperview:(NSView*)view {
37 if (self = [super init]) {
38 // Disable the fade-in animation as the layer and view are added.
39 ScopedCAActionDisabler disabler;
41 // Make this view host a transparent layer.
42 background_layer_.reset([[CALayer alloc] init]);
43 [background_layer_ setContentsGravity:kCAGravityTopLeft];
44 [self setLayer:background_layer_];
45 [self setWantsLayer:YES];
47 compositor_.reset(new ui::Compositor(self));
48 [view addSubview:self];
53 // This function closely mirrors RenderWidgetHostViewMac::LayoutLayers. When
54 // only delegated rendering is supported, only one copy of this code will
56 - (void)layoutLayers {
57 // Disable animation of the layers' resizing or repositioning.
58 ScopedCAActionDisabler disabler;
60 NSSize superview_frame_size = [[self superview] frame].size;
61 [self setFrame:NSMakeRect(
62 0, 0, superview_frame_size.width, superview_frame_size.height)];
64 CGRect new_background_frame = CGRectMake(
67 superview_frame_size.width,
68 superview_frame_size.height);
69 [background_layer_ setFrame:new_background_frame];
71 // The bounds of the accelerated layer determine the size of the GL surface
72 // that will be drawn to. Make sure that this is big enough to draw the
74 if (accelerated_layer_) {
75 CGRect layer_bounds = CGRectMake(
78 [accelerated_layer_ iosurface]->dip_io_surface_size().width(),
79 [accelerated_layer_ iosurface]->dip_io_surface_size().height());
80 CGPoint layer_position = CGPointMake(
82 CGRectGetHeight(new_background_frame) - CGRectGetHeight(layer_bounds));
83 bool bounds_changed = !CGRectEqualToRect(
84 layer_bounds, [accelerated_layer_ bounds]);
85 [accelerated_layer_ setBounds:layer_bounds];
86 [accelerated_layer_ setPosition:layer_position];
88 [accelerated_layer_ setNeedsDisplay];
89 [accelerated_layer_ displayIfNeeded];
93 // The content area of the software layer is the size of the image provided.
94 // Make the bounds of the layer match the superview's bounds, to ensure that
95 // the visible contents are drawn.
96 [software_layer_ setBounds:new_background_frame];
99 - (ui::Compositor*)compositor {
100 return compositor_.get();
103 - (void)gotAcceleratedIOSurfaceFrame:(uint64)surface_handle
104 withPixelSize:(gfx::Size)pixel_size
105 withScaleFactor:(float)scale_factor {
106 ScopedCAActionDisabler disabler;
108 // If there is not a layer for accelerated frames, create one.
109 if (!accelerated_layer_) {
110 // Disable the fade-in animation as the layer is added.
111 ScopedCAActionDisabler disabler;
112 scoped_refptr<content::CompositingIOSurfaceMac> iosurface =
113 content::CompositingIOSurfaceMac::Create();
114 accelerated_layer_.reset([[CompositingIOSurfaceLayer alloc]
115 initWithIOSurface:iosurface
117 [[self layer] addSublayer:accelerated_layer_];
122 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
123 [accelerated_layer_ context]->cgl_context());
124 result = [accelerated_layer_ iosurface]->SetIOSurfaceWithContextCurrent(
125 [accelerated_layer_ context], surface_handle, pixel_size, scale_factor);
126 // TODO(ccameron): On failure, poison the GL context, tear down the layers,
127 // and request a new frame.
128 ignore_result(result);
130 [accelerated_layer_ gotNewFrame];
133 // If there was a software layer, remove it.
134 if (software_layer_) {
135 // Disable the fade-out animation as the layer is removed.
136 ScopedCAActionDisabler disabler;
137 [software_layer_ removeFromSuperlayer];
138 software_layer_.reset();
142 - (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data
143 withScaleFactor:(float)scale_factor
144 withCanvas:(SkCanvas*)canvas {
145 if (!frame_data || !canvas)
148 // If there is not a layer for software frames, create one.
149 if (!software_layer_) {
150 // Disable the fade-in animation as the layer is added.
151 ScopedCAActionDisabler disabler;
152 software_layer_.reset([[SoftwareLayer alloc] init]);
153 [[self layer] addSublayer:software_layer_];
158 const void* pixels = canvas->peekPixels(&info, &row_bytes);
159 [software_layer_ setContentsToData:pixels
160 withRowBytes:row_bytes
161 withPixelSize:gfx::Size(info.fWidth, info.fHeight)
162 withScaleFactor:scale_factor];
165 // If there was an accelerated layer, remove it.
166 if (accelerated_layer_) {
167 // Disable the fade-out animation as the layer is removed.
168 ScopedCAActionDisabler disabler;
169 [accelerated_layer_ removeFromSuperlayer];
170 accelerated_layer_.reset();
174 @end // BrowserCompositorViewMac