Commit 63c74fe8 authored by ccameron@chromium.org's avatar ccameron@chromium.org

Fix flipped views on Mac

Setting a layer-hosting NSView's CALayer's geometry flipping has a lot
of unexpected side-effects, and is proving unsafe, especially if that
NSView will have sub-views.

Add a level of indirection where the hosted layer is not flipped, but it
has a sub-layer that is flipped, off of which the layers for composited
content are attached.

BUG=392952

Review URL: https://codereview.chromium.org/392143002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283862 0039d316-1c4b-4281-b951-d872f2087c98
parent b7eea2ff
...@@ -2,3 +2,4 @@ piman@chromium.org ...@@ -2,3 +2,4 @@ piman@chromium.org
danakj@chromium.org danakj@chromium.org
sievers@chromium.org sievers@chromium.org
jbauman@chromium.org jbauman@chromium.org
ccameron@chromium.org
...@@ -17,10 +17,19 @@ class BrowserCompositorViewCocoaHelper; ...@@ -17,10 +17,19 @@ class BrowserCompositorViewCocoaHelper;
@interface BrowserCompositorViewCocoa : NSView { @interface BrowserCompositorViewCocoa : NSView {
scoped_ptr<ui::Compositor> compositor_; scoped_ptr<ui::Compositor> compositor_;
base::scoped_nsobject<CALayer> background_layer_; // A flipped layer, which acts as the parent of the compositing and software
// layers. This layer is flipped so that the we don't need to recompute the
// origin for sub-layers when their position changes (this is impossible when
// using remote layers, as their size change cannot be synchronized with the
// window). This indirection is needed because flipping hosted layers (like
// |background_layer_| of RenderWidgetHostViewCocoa) leads to unpredictable
// behavior.
base::scoped_nsobject<CALayer> flipped_layer_;
base::scoped_nsobject<CompositingIOSurfaceLayer> accelerated_layer_; base::scoped_nsobject<CompositingIOSurfaceLayer> accelerated_layer_;
int accelerated_layer_output_surface_id_; int accelerated_layer_output_surface_id_;
std::vector<ui::LatencyInfo> accelerated_latency_info_; std::vector<ui::LatencyInfo> accelerated_latency_info_;
base::scoped_nsobject<SoftwareLayer> software_layer_; base::scoped_nsobject<SoftwareLayer> software_layer_;
content::BrowserCompositorViewMacClient* client_; content::BrowserCompositorViewMacClient* client_;
......
...@@ -27,11 +27,14 @@ ...@@ -27,11 +27,14 @@
// Disable the fade-in animation as the layer and view are added. // Disable the fade-in animation as the layer and view are added.
ScopedCAActionDisabler disabler; ScopedCAActionDisabler disabler;
// Make this view host a transparent layer. // Add a flipped transparent layer as a child, so that we don't need to
background_layer_.reset([[CALayer alloc] init]); // fiddle with the position of sub-layers -- they will always be at the
[background_layer_ setContentsGravity:kCAGravityTopLeft]; // origin.
[self setLayer:background_layer_]; flipped_layer_.reset([[CALayer alloc] init]);
[self setWantsLayer:YES]; [flipped_layer_ setGeometryFlipped:YES];
[flipped_layer_ setAnchorPoint:CGPointMake(0, 0)];
[flipped_layer_
setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable];
compositor_.reset(new ui::Compositor(self, content::GetContextFactory())); compositor_.reset(new ui::Compositor(self, content::GetContextFactory()));
} }
...@@ -41,9 +44,9 @@ ...@@ -41,9 +44,9 @@
- (void)setClient:(content::BrowserCompositorViewMacClient*)client { - (void)setClient:(content::BrowserCompositorViewMacClient*)client {
// Disable the fade-out as layers are removed. // Disable the fade-out as layers are removed.
ScopedCAActionDisabler disabler; ScopedCAActionDisabler disabler;
[self removeFromSuperview];
// Reset all state. // Reset all state.
[flipped_layer_ removeFromSuperlayer];
[accelerated_layer_ removeFromSuperlayer]; [accelerated_layer_ removeFromSuperlayer];
[accelerated_layer_ resetClient]; [accelerated_layer_ resetClient];
accelerated_layer_.reset(); accelerated_layer_.reset();
...@@ -56,7 +59,10 @@ ...@@ -56,7 +59,10 @@
if (client_) { if (client_) {
DCHECK(compositor_); DCHECK(compositor_);
compositor_->SetRootLayer(client_->BrowserCompositorRootLayer()); compositor_->SetRootLayer(client_->BrowserCompositorRootLayer());
[client_->BrowserCompositorSuperview() addSubview:self]; CALayer* background_layer = [client_->BrowserCompositorSuperview() layer];
DCHECK(background_layer);
[flipped_layer_ setBounds:[background_layer bounds]];
[background_layer addSublayer:flipped_layer_];
} else { } else {
compositor_->SetRootLayer(NULL); compositor_->SetRootLayer(NULL);
} }
...@@ -111,7 +117,7 @@ ...@@ -111,7 +117,7 @@
initWithIOSurface:iosurface initWithIOSurface:iosurface
withScaleFactor:scale_factor withScaleFactor:scale_factor
withClient:helper_.get()]); withClient:helper_.get()]);
[[self layer] addSublayer:accelerated_layer_]; [flipped_layer_ addSublayer:accelerated_layer_];
} }
{ {
...@@ -163,7 +169,7 @@ ...@@ -163,7 +169,7 @@
// Disable the fade-in animation as the layer is added. // Disable the fade-in animation as the layer is added.
ScopedCAActionDisabler disabler; ScopedCAActionDisabler disabler;
software_layer_.reset([[SoftwareLayer alloc] init]); software_layer_.reset([[SoftwareLayer alloc] init]);
[[self layer] addSublayer:software_layer_]; [flipped_layer_ addSublayer:software_layer_];
} }
SkImageInfo info; SkImageInfo info;
......
...@@ -411,9 +411,16 @@ class CONTENT_EXPORT RenderWidgetHostViewMac ...@@ -411,9 +411,16 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
bool can_compose_inline_; bool can_compose_inline_;
// The background CoreAnimation layer which is hosted by |cocoa_view_|. // The background CoreAnimation layer which is hosted by |cocoa_view_|.
// The compositing or software layers will be added as sublayers to this.
base::scoped_nsobject<CALayer> background_layer_; base::scoped_nsobject<CALayer> background_layer_;
// A flipped layer, which acts as the parent of the compositing and software
// layers. This layer is flipped so that the we don't need to recompute the
// origin for sub-layers when their position changes (this is impossible when
// using remote layers, as their size change cannot be synchronized with the
// window). This indirection is needed because flipping hosted layers (like
// |background_layer_|) leads to unpredictable behavior.
base::scoped_nsobject<CALayer> flipped_layer_;
// The CoreAnimation layer hosted by the GPU process. // The CoreAnimation layer hosted by the GPU process.
base::scoped_nsobject<CALayerHost> remote_layer_host_; base::scoped_nsobject<CALayerHost> remote_layer_host_;
......
...@@ -513,14 +513,25 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) ...@@ -513,14 +513,25 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget)
cocoa_view_ = [[[RenderWidgetHostViewCocoa alloc] cocoa_view_ = [[[RenderWidgetHostViewCocoa alloc]
initWithRenderWidgetHostViewMac:this] autorelease]; initWithRenderWidgetHostViewMac:this] autorelease];
// Make this view host a solid white layer when there is no content ready to
// draw.
background_layer_.reset([[CALayer alloc] init]); background_layer_.reset([[CALayer alloc] init]);
[background_layer_ [background_layer_
setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)]; setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
[background_layer_ setGeometryFlipped:YES];
[background_layer_ setContentsGravity:kCAGravityTopLeft];
[cocoa_view_ setLayer:background_layer_]; [cocoa_view_ setLayer:background_layer_];
[cocoa_view_ setWantsLayer:YES]; [cocoa_view_ setWantsLayer:YES];
if (!IsDelegatedRendererEnabled()) {
// Add a flipped transparent layer as a child, so that we don't need to
// fiddle with the position of sub-layers -- they will always be at the
// origin.
flipped_layer_.reset([[CALayer alloc] init]);
[flipped_layer_ setGeometryFlipped:YES];
[flipped_layer_
setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable];
[background_layer_ addSublayer:flipped_layer_];
}
if (IsDelegatedRendererEnabled()) { if (IsDelegatedRendererEnabled()) {
root_layer_.reset(new ui::Layer(ui::LAYER_TEXTURED)); root_layer_.reset(new ui::Layer(ui::LAYER_TEXTURED));
delegated_frame_host_.reset(new DelegatedFrameHost(this)); delegated_frame_host_.reset(new DelegatedFrameHost(this));
...@@ -653,7 +664,7 @@ void RenderWidgetHostViewMac::EnsureSoftwareLayer() { ...@@ -653,7 +664,7 @@ void RenderWidgetHostViewMac::EnsureSoftwareLayer() {
// Disable the fade-in animation as the layer is added. // Disable the fade-in animation as the layer is added.
ScopedCAActionDisabler disabler; ScopedCAActionDisabler disabler;
[background_layer_ addSublayer:software_layer_]; [flipped_layer_ addSublayer:software_layer_];
} }
void RenderWidgetHostViewMac::DestroySoftwareLayer() { void RenderWidgetHostViewMac::DestroySoftwareLayer() {
...@@ -681,7 +692,7 @@ void RenderWidgetHostViewMac::EnsureCompositedIOSurfaceLayer() { ...@@ -681,7 +692,7 @@ void RenderWidgetHostViewMac::EnsureCompositedIOSurfaceLayer() {
// Disable the fade-in animation as the layer is added. // Disable the fade-in animation as the layer is added.
ScopedCAActionDisabler disabler; ScopedCAActionDisabler disabler;
[background_layer_ addSublayer:compositing_iosurface_layer_]; [flipped_layer_ addSublayer:compositing_iosurface_layer_];
} }
void RenderWidgetHostViewMac::DestroyCompositedIOSurfaceLayer( void RenderWidgetHostViewMac::DestroyCompositedIOSurfaceLayer(
...@@ -1754,7 +1765,7 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( ...@@ -1754,7 +1765,7 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped(
[remote_layer_host_ setContextId:context_id]; [remote_layer_host_ setContextId:context_id];
[remote_layer_host_ [remote_layer_host_
setAutoresizingMask:kCALayerMaxXMargin|kCALayerMaxYMargin]; setAutoresizingMask:kCALayerMaxXMargin|kCALayerMaxYMargin];
[background_layer_ addSublayer:remote_layer_host_]; [flipped_layer_ addSublayer:remote_layer_host_];
} }
// Ack the frame immediately. Any GPU back pressure will be applied by // Ack the frame immediately. Any GPU back pressure will be applied by
...@@ -2192,7 +2203,7 @@ void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() { ...@@ -2192,7 +2203,7 @@ void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() {
// Synchronized resizing does not yet work with browser compositor. // Synchronized resizing does not yet work with browser compositor.
// http://crbug.com/388005 // http://crbug.com/388005
if (delegated_frame_host_) if (IsDelegatedRendererEnabled())
return; return;
// Pausing for one view prevents others from receiving frames. // Pausing for one view prevents others from receiving frames.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment