Commit a71197c1 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

BrowserCompositorMac: Remove detached compositor state

With MacViews, it is now very rare to actually need a
RenderWidgetHostViewMac to have its own compositor. The only
circumstances where this happens are
- content shell
- popup windows (the date/time picker)
- tab capture of backgrounded tabs

Remove the concept of having a "detached" compositor, and simplify
the transitions between states. This change will introduce flashes to
paths that rely on the RenderWidgetHostViewMac having its own
compositor (which are now vanishingly rare).

Change-Id: I0feeec67a42f05de05aa4d72fe9af93f033d9d64
Reviewed-on: https://chromium-review.googlesource.com/c/1292377
Commit-Queue: ccameron <ccameron@chromium.org>
Commit-Queue: Fady Samuel <fsamuel@chromium.org>
Reviewed-by: default avatarFady Samuel <fsamuel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601409}
parent 4580e632
...@@ -159,28 +159,14 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient, ...@@ -159,28 +159,14 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
cc::DeadlinePolicy GetDeadlinePolicy(bool is_resize) const; cc::DeadlinePolicy GetDeadlinePolicy(bool is_resize) const;
// The state of |delegated_frame_host_| and |recyclable_compositor_| to // The state of |delegated_frame_host_| and |recyclable_compositor_| to
// manage being visible, occluded, hidden, or drawn via a ui::Layer. Note that // manage being visible, hidden, or drawn via a ui::Layer.
// TransitionToState will transition through each intermediate state according
// to enum values (e.g, going from HasAttachedCompositor to HasNoCompositor
// will temporarily go through HasDetachedCompositor).
enum State { enum State {
// Effects: // Effects:
// - |recyclable_compositor_| exists and is attached to // - |recyclable_compositor_| exists and is attached to
// |delegated_frame_host_|. // |delegated_frame_host_|.
// Happens when: // Happens when:
// - |render_widet_host_| is in the visible state. // - |render_widet_host_| is in the visible state.
HasAttachedCompositor = 0, HasAttachedCompositor,
// Effects:
// - |recyclable_compositor_| exists, but |delegated_frame_host_| is
// hidden and detached from it.
// Happens when:
// - The |render_widget_host_| is hidden, but |cocoa_view_| is still in the
// NSWindow hierarchy (e.g, when the window is occluded or offscreen).
// - Note: In this state, |recyclable_compositor_| and its CALayers are kept
// around so that we will have content to show when we are un-occluded. If
// we had a way to keep the CALayers attached to the NSView while
// detaching the ui::Compositor, then there would be no need for this
HasDetachedCompositor = 1,
// Effects: // Effects:
// - |recyclable_compositor_| has been recycled and |delegated_frame_host_| // - |recyclable_compositor_| has been recycled and |delegated_frame_host_|
// is hidden and detached from it. // is hidden and detached from it.
...@@ -188,13 +174,13 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient, ...@@ -188,13 +174,13 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
// - The |render_widget_host_| hidden or gone, and |cocoa_view_| is not // - The |render_widget_host_| hidden or gone, and |cocoa_view_| is not
// attached to an NSWindow. // attached to an NSWindow.
// - This happens for backgrounded tabs. // - This happens for backgrounded tabs.
HasNoCompositor = 2, HasNoCompositor,
// Effects: // Effects:
// - |recyclable_compositor_| does not exist. |delegated_frame_host_| is // - |recyclable_compositor_| does not exist. |delegated_frame_host_| is
// attached to |parent_ui_layer_|'s compositor. // attached to |parent_ui_layer_|'s compositor.
// Happens when: // Happens when:
// - |parent_ui_layer_| is non-nullptr. // - |parent_ui_layer_| is non-nullptr.
UseParentLayerCompositor = 3, UseParentLayerCompositor,
}; };
State state_ = HasNoCompositor; State state_ = HasNoCompositor;
void UpdateState(); void UpdateState();
......
...@@ -90,8 +90,6 @@ void BrowserCompositorMac::ClearCompositorFrame() { ...@@ -90,8 +90,6 @@ void BrowserCompositorMac::ClearCompositorFrame() {
// compositor. This ensures that we are able to swap in a new blank frame to // compositor. This ensures that we are able to swap in a new blank frame to
// replace any old content. // replace any old content.
// https://crbug.com/739621 // https://crbug.com/739621
if (recyclable_compositor_)
recyclable_compositor_->Unsuspend();
if (delegated_frame_host_) if (delegated_frame_host_)
delegated_frame_host_->ClearDelegatedFrame(); delegated_frame_host_->ClearDelegatedFrame();
} }
...@@ -155,8 +153,6 @@ bool BrowserCompositorMac::UpdateNSViewAndDisplay( ...@@ -155,8 +153,6 @@ bool BrowserCompositorMac::UpdateNSViewAndDisplay(
root_layer_->SetBounds(gfx::Rect(dfh_size_dip_)); root_layer_->SetBounds(gfx::Rect(dfh_size_dip_));
if (needs_new_surface_id) { if (needs_new_surface_id) {
if (recyclable_compositor_)
recyclable_compositor_->Suspend();
GetDelegatedFrameHost()->EmbedSurface( GetDelegatedFrameHost()->EmbedSurface(
dfh_local_surface_id_allocator_.GenerateId(), dfh_size_dip_, dfh_local_surface_id_allocator_.GenerateId(), dfh_size_dip_,
GetDeadlinePolicy(is_resize)); GetDeadlinePolicy(is_resize));
...@@ -239,13 +235,6 @@ void BrowserCompositorMac::UpdateState() { ...@@ -239,13 +235,6 @@ void BrowserCompositorMac::UpdateState() {
return; return;
} }
// If the host is not visible but we are attached to a window then keep around
// a compositor only if it already exists.
if (ns_view_attached_to_window_ && state_ == HasAttachedCompositor) {
TransitionToState(HasDetachedCompositor);
return;
}
// Otherwise put the compositor up for recycling. // Otherwise put the compositor up for recycling.
TransitionToState(HasNoCompositor); TransitionToState(HasNoCompositor);
} }
...@@ -258,7 +247,7 @@ void BrowserCompositorMac::TransitionToState(State new_state) { ...@@ -258,7 +247,7 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
// transition will be made if we are already in UseParentLayerCompositor, but // transition will be made if we are already in UseParentLayerCompositor, but
// with a different parent layer. // with a different parent layer.
if (state_ == UseParentLayerCompositor && if (state_ == UseParentLayerCompositor &&
(new_state < UseParentLayerCompositor || (new_state != UseParentLayerCompositor ||
parent_ui_layer_ != root_layer_->parent())) { parent_ui_layer_ != root_layer_->parent())) {
DCHECK(root_layer_->parent()); DCHECK(root_layer_->parent());
root_layer_->parent()->RemoveObserver(this); root_layer_->parent()->RemoveObserver(this);
...@@ -268,8 +257,8 @@ void BrowserCompositorMac::TransitionToState(State new_state) { ...@@ -268,8 +257,8 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
state_ = HasNoCompositor; state_ = HasNoCompositor;
} }
// Transition HasNoCompositor -> HasDetachedCompositor. // Transition HasNoCompositor -> HasAttachedCompositor.
if (state_ == HasNoCompositor && new_state < HasNoCompositor) { if (state_ == HasNoCompositor && new_state == HasAttachedCompositor) {
recyclable_compositor_ = recyclable_compositor_ =
ui::RecyclableCompositorMacFactory::Get()->CreateCompositor( ui::RecyclableCompositorMacFactory::Get()->CreateCompositor(
content::GetContextFactory(), content::GetContextFactoryPrivate()); content::GetContextFactory(), content::GetContextFactoryPrivate());
...@@ -281,38 +270,20 @@ void BrowserCompositorMac::TransitionToState(State new_state) { ...@@ -281,38 +270,20 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
dfh_display_.color_space()); dfh_display_.color_space());
recyclable_compositor_->widget()->SetNSView( recyclable_compositor_->widget()->SetNSView(
accelerated_widget_mac_ns_view_); accelerated_widget_mac_ns_view_);
state_ = HasDetachedCompositor;
}
// Transition HasDetachedCompositor -> HasAttachedCompositor.
if (state_ == HasDetachedCompositor && new_state < HasDetachedCompositor) {
delegated_frame_host_->AttachToCompositor( delegated_frame_host_->AttachToCompositor(
recyclable_compositor_->compositor()); recyclable_compositor_->compositor());
delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_, delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
false /* record_presentation_time */); false /* record_presentation_time */);
// If there exists a saved frame ready to display, unsuspend the compositor
// now (if one is not ready, the compositor will unsuspend on first surface
// activation).
if (delegated_frame_host_->HasActiveSurface())
recyclable_compositor_->Unsuspend(); recyclable_compositor_->Unsuspend();
state_ = HasAttachedCompositor; state_ = HasAttachedCompositor;
} }
// Transition HasAttachedCompositor -> HasDetachedCompositor. // Transition HasAttachedCompositor -> HasNoCompositor.
if (state_ == HasAttachedCompositor && new_state > HasAttachedCompositor) { if (state_ == HasAttachedCompositor && new_state != HasAttachedCompositor) {
// Ensure that any changes made to the ui::Compositor do not result in new
// frames being produced.
recyclable_compositor_->Suspend();
// Marking the DelegatedFrameHost as removed from the window hierarchy is // Marking the DelegatedFrameHost as removed from the window hierarchy is
// necessary to remove all connections to its old ui::Compositor. // necessary to remove all connections to its old ui::Compositor.
delegated_frame_host_->WasHidden(); delegated_frame_host_->WasHidden();
delegated_frame_host_->DetachFromCompositor(); delegated_frame_host_->DetachFromCompositor();
state_ = HasDetachedCompositor;
}
// Transition HasDetachedCompositor -> HasNoCompositor.
if (state_ == HasDetachedCompositor && new_state > HasDetachedCompositor) {
recyclable_compositor_->widget()->ResetNSView(); recyclable_compositor_->widget()->ResetNSView();
recyclable_compositor_->compositor()->SetRootLayer(nullptr); recyclable_compositor_->compositor()->SetRootLayer(nullptr);
recyclable_compositor_->InvalidateSurface(); recyclable_compositor_->InvalidateSurface();
...@@ -322,7 +293,7 @@ void BrowserCompositorMac::TransitionToState(State new_state) { ...@@ -322,7 +293,7 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
} }
// Transition HasNoCompositor -> UseParentLayerCompositor. // Transition HasNoCompositor -> UseParentLayerCompositor.
if (state_ == HasNoCompositor && new_state > HasNoCompositor) { if (state_ == HasNoCompositor && new_state == UseParentLayerCompositor) {
DCHECK(parent_ui_layer_); DCHECK(parent_ui_layer_);
DCHECK(parent_ui_layer_->GetCompositor()); DCHECK(parent_ui_layer_->GetCompositor());
DCHECK(!root_layer_->parent()); DCHECK(!root_layer_->parent());
...@@ -362,12 +333,6 @@ void BrowserCompositorMac::TakeFallbackContentFrom( ...@@ -362,12 +333,6 @@ void BrowserCompositorMac::TakeFallbackContentFrom(
BrowserCompositorMac* other) { BrowserCompositorMac* other) {
delegated_frame_host_->TakeFallbackContentFrom( delegated_frame_host_->TakeFallbackContentFrom(
other->delegated_frame_host_.get()); other->delegated_frame_host_.get());
// We will have a flash if we can't recycle the compositor from |other|.
if (other->state_ == HasDetachedCompositor && state_ == HasNoCompositor) {
other->TransitionToState(HasNoCompositor);
TransitionToState(HasAttachedCompositor);
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -387,10 +352,6 @@ SkColor BrowserCompositorMac::DelegatedFrameHostGetGutterColor() const { ...@@ -387,10 +352,6 @@ SkColor BrowserCompositorMac::DelegatedFrameHostGetGutterColor() const {
void BrowserCompositorMac::OnFirstSurfaceActivation( void BrowserCompositorMac::OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) { const viz::SurfaceInfo& surface_info) {
if (!recyclable_compositor_)
return;
recyclable_compositor_->Unsuspend();
} }
void BrowserCompositorMac::OnBeginFrame(base::TimeTicks frame_time) { void BrowserCompositorMac::OnBeginFrame(base::TimeTicks frame_time) {
......
...@@ -2014,7 +2014,7 @@ TEST_F(RenderWidgetHostViewMacTest, ClearCompositorFrame) { ...@@ -2014,7 +2014,7 @@ TEST_F(RenderWidgetHostViewMacTest, ClearCompositorFrame) {
BrowserCompositorMac* browser_compositor = rwhv_mac_->BrowserCompositor(); BrowserCompositorMac* browser_compositor = rwhv_mac_->BrowserCompositor();
ui::Compositor* ui_compositor = browser_compositor->GetCompositor(); ui::Compositor* ui_compositor = browser_compositor->GetCompositor();
EXPECT_NE(ui_compositor, nullptr); EXPECT_NE(ui_compositor, nullptr);
EXPECT_TRUE(ui_compositor->IsLocked()); EXPECT_FALSE(ui_compositor->IsLocked());
rwhv_mac_->ClearCompositorFrame(); rwhv_mac_->ClearCompositorFrame();
EXPECT_EQ(browser_compositor->GetCompositor(), ui_compositor); EXPECT_EQ(browser_compositor->GetCompositor(), ui_compositor);
EXPECT_FALSE(ui_compositor->IsLocked()); EXPECT_FALSE(ui_compositor->IsLocked());
......
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