Commit 5a68e397 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

mac: Destroy all ui::Compositors at shutdown

It used to be a valid assumption that ui::Compositors would be destroyed
before BrowserCompositorMac::DisableRecyclingForShutdown was called, but
changes to NSWindows' lifetimes have made that assumption no longer
valid.

Destroy all BrowserCompositorMac instances at that call. Make relevant
methods on RenderWidgetHostViewCocoa and RenderWidgetHostViewMac
early-out when the BrowserCompositorMac is gone.

Bug: 805726
Change-Id: I429b6b546344a23cd93e64dae4a004065328d5a6
Reviewed-on: https://chromium-review.googlesource.com/947813
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarTrent Apted <tapted@chromium.org>
Cr-Commit-Position: refs/heads/master@{#540798}
parent 7ba6b7dd
...@@ -30,6 +30,7 @@ class BrowserCompositorMacClient { ...@@ -30,6 +30,7 @@ class BrowserCompositorMacClient {
virtual void BrowserCompositorMacOnBeginFrame() = 0; virtual void BrowserCompositorMacOnBeginFrame() = 0;
virtual void OnFrameTokenChanged(uint32_t frame_token) = 0; virtual void OnFrameTokenChanged(uint32_t frame_token) = 0;
virtual void DidReceiveFirstFrameAfterNavigation() = 0; virtual void DidReceiveFirstFrameAfterNavigation() = 0;
virtual void DestroyCompositorForShutdown() = 0;
}; };
// This class owns a DelegatedFrameHost, and will dynamically attach and // This class owns a DelegatedFrameHost, and will dynamically attach and
......
...@@ -28,13 +28,15 @@ namespace content { ...@@ -28,13 +28,15 @@ namespace content {
namespace { namespace {
// Set when no browser compositors should remain alive. // Weak pointers to all BrowserCompositorMac instances, used to
bool g_has_shut_down = false; // - Determine if a spare RecyclableCompositorMac should be kept around (one
// should be only if there exists at least one BrowserCompositorMac).
// The number of placeholder objects allocated. If this reaches zero, then // - Force all ui::Compositors to be destroyed at shut-down (because the NSView
// the RecyclableCompositorMac being held on to for recycling, // signals to shut down will come in very late, long after things that the
// |g_spare_recyclable_compositors|, will be freed. // ui::Compositor depend on have been destroyed).
uint32_t g_browser_compositor_count = 0; // https://crbug.com/805726
base::LazyInstance<std::set<BrowserCompositorMac*>>::Leaky
g_browser_compositors;
// A spare RecyclableCompositorMac kept around for recycling. // A spare RecyclableCompositorMac kept around for recycling.
base::LazyInstance<base::circular_deque< base::LazyInstance<base::circular_deque<
...@@ -46,7 +48,7 @@ void ReleaseSpareCompositors() { ...@@ -46,7 +48,7 @@ void ReleaseSpareCompositors() {
while (g_spare_recyclable_compositors.Get().size() > 1) while (g_spare_recyclable_compositors.Get().size() > 1)
g_spare_recyclable_compositors.Get().pop_front(); g_spare_recyclable_compositors.Get().pop_front();
if (!g_browser_compositor_count) if (g_browser_compositors.Get().empty())
g_spare_recyclable_compositors.Get().clear(); g_spare_recyclable_compositors.Get().clear();
} }
...@@ -69,10 +71,6 @@ class RecyclableCompositorMac : public ui::CompositorObserver { ...@@ -69,10 +71,6 @@ class RecyclableCompositorMac : public ui::CompositorObserver {
// Delete a compositor, or allow it to be recycled. // Delete a compositor, or allow it to be recycled.
static void Recycle(std::unique_ptr<RecyclableCompositorMac> compositor); static void Recycle(std::unique_ptr<RecyclableCompositorMac> compositor);
// Indicate that the recyclable compositor should be destroyed, and no future
// compositors should be recycled.
static void DisableRecyclingForShutdown();
ui::Compositor* compositor() { return &compositor_; } ui::Compositor* compositor() { return &compositor_; }
ui::AcceleratedWidgetMac* accelerated_widget_mac() { ui::AcceleratedWidgetMac* accelerated_widget_mac() {
return accelerated_widget_mac_.get(); return accelerated_widget_mac_.get();
...@@ -153,11 +151,6 @@ std::unique_ptr<RecyclableCompositorMac> RecyclableCompositorMac::Create() { ...@@ -153,11 +151,6 @@ std::unique_ptr<RecyclableCompositorMac> RecyclableCompositorMac::Create() {
// static // static
void RecyclableCompositorMac::Recycle( void RecyclableCompositorMac::Recycle(
std::unique_ptr<RecyclableCompositorMac> compositor) { std::unique_ptr<RecyclableCompositorMac> compositor) {
// It is an error to have a browser compositor continue to exist after
// shutdown.
CHECK(!g_has_shut_down);
CHECK(compositor);
CHECK(content::ImageTransportFactory::GetInstance());
content::ImageTransportFactory::GetInstance() content::ImageTransportFactory::GetInstance()
->SetCompositorSuspendedForRecycle(compositor->compositor(), true); ->SetCompositorSuspendedForRecycle(compositor->compositor(), true);
...@@ -183,7 +176,7 @@ BrowserCompositorMac::BrowserCompositorMac( ...@@ -183,7 +176,7 @@ BrowserCompositorMac::BrowserCompositorMac(
: client_(client), : client_(client),
accelerated_widget_mac_ns_view_(accelerated_widget_mac_ns_view), accelerated_widget_mac_ns_view_(accelerated_widget_mac_ns_view),
weak_factory_(this) { weak_factory_(this) {
g_browser_compositor_count += 1; g_browser_compositors.Get().insert(this);
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
delegated_frame_host_.reset(new DelegatedFrameHost( delegated_frame_host_.reset(new DelegatedFrameHost(
...@@ -206,12 +199,12 @@ BrowserCompositorMac::~BrowserCompositorMac() { ...@@ -206,12 +199,12 @@ BrowserCompositorMac::~BrowserCompositorMac() {
delegated_frame_host_.reset(); delegated_frame_host_.reset();
root_layer_.reset(); root_layer_.reset();
DCHECK_GT(g_browser_compositor_count, 0u); size_t num_erased = g_browser_compositors.Get().erase(this);
g_browser_compositor_count -= 1; DCHECK_EQ(1u, num_erased);
// If there are no compositors allocated, destroy the recyclable // If there are no compositors allocated, destroy the recyclable
// RecyclableCompositorMac. // RecyclableCompositorMac.
if (!g_browser_compositor_count) if (g_browser_compositors.Get().empty())
g_spare_recyclable_compositors.Get().clear(); g_spare_recyclable_compositors.Get().clear();
} }
...@@ -411,7 +404,14 @@ void BrowserCompositorMac::TransitionToState(State new_state) { ...@@ -411,7 +404,14 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
// static // static
void BrowserCompositorMac::DisableRecyclingForShutdown() { void BrowserCompositorMac::DisableRecyclingForShutdown() {
g_has_shut_down = true; // Ensure that the client has destroyed its BrowserCompositorViewMac before
// it dependencies are destroyed.
// https://crbug.com/805726
while (!g_browser_compositors.Get().empty()) {
BrowserCompositorMac* browser_compositor =
*g_browser_compositors.Get().begin();
browser_compositor->client_->DestroyCompositorForShutdown();
}
g_spare_recyclable_compositors.Get().clear(); g_spare_recyclable_compositors.Get().clear();
} }
......
...@@ -493,6 +493,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac ...@@ -493,6 +493,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void BrowserCompositorMacOnBeginFrame() override; void BrowserCompositorMacOnBeginFrame() override;
void OnFrameTokenChanged(uint32_t frame_token) override; void OnFrameTokenChanged(uint32_t frame_token) override;
void DidReceiveFirstFrameAfterNavigation() override; void DidReceiveFirstFrameAfterNavigation() override;
void DestroyCompositorForShutdown() override;
// AcceleratedWidgetMacNSView implementation. // AcceleratedWidgetMacNSView implementation.
NSView* AcceleratedWidgetGetNSView() const override; NSView* AcceleratedWidgetGetNSView() const override;
......
...@@ -401,6 +401,10 @@ void RenderWidgetHostViewMac::DidReceiveFirstFrameAfterNavigation() { ...@@ -401,6 +401,10 @@ void RenderWidgetHostViewMac::DidReceiveFirstFrameAfterNavigation() {
render_widget_host_->DidReceiveFirstFrameAfterNavigation(); render_widget_host_->DidReceiveFirstFrameAfterNavigation();
} }
void RenderWidgetHostViewMac::DestroyCompositorForShutdown() {
browser_compositor_.reset();
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// AcceleratedWidgetMacNSView, public: // AcceleratedWidgetMacNSView, public:
...@@ -729,7 +733,7 @@ RenderWidgetHostViewMac::GetFocusedRenderWidgetHostDelegate() { ...@@ -729,7 +733,7 @@ RenderWidgetHostViewMac::GetFocusedRenderWidgetHostDelegate() {
} }
void RenderWidgetHostViewMac::UpdateNSViewAndDisplayProperties() { void RenderWidgetHostViewMac::UpdateNSViewAndDisplayProperties() {
if (!render_widget_host_) if (!browser_compositor_)
return; return;
// During auto-resize it is the responsibility of the caller to ensure that // During auto-resize it is the responsibility of the caller to ensure that
...@@ -1729,8 +1733,10 @@ void RenderWidgetHostViewMac::OnGetRenderedTextCompleted( ...@@ -1729,8 +1733,10 @@ void RenderWidgetHostViewMac::OnGetRenderedTextCompleted(
} }
void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() { void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() {
if (!render_widget_host_ || render_widget_host_->is_hidden()) if (!render_widget_host_ || !browser_compositor_ ||
render_widget_host_->is_hidden()) {
return; return;
}
// Pausing for one view prevents others from receiving frames. // Pausing for one view prevents others from receiving frames.
// This may lead to large delays, causing overlaps. See crbug.com/352020. // This may lead to large delays, causing overlaps. See crbug.com/352020.
...@@ -3483,6 +3489,12 @@ extern NSString *NSTextInputReplacementRangeAttributeName; ...@@ -3483,6 +3489,12 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
} }
- (void)viewDidMoveToWindow { - (void)viewDidMoveToWindow {
// This can be called very late during shutdown, so it needs to be guarded by
// a check that DestroyCompositorForShutdown has not yet been called.
// https://crbug.com/805726
if (!renderWidgetHostView_->browser_compositor_)
return;
if ([self window]) if ([self window])
[self updateScreenProperties]; [self updateScreenProperties];
renderWidgetHostView_->browser_compositor_->SetNSViewAttachedToWindow( renderWidgetHostView_->browser_compositor_->SetNSViewAttachedToWindow(
......
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