// 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 #include #include "base/lazy_instance.h" #include "base/trace_event/trace_event.h" #include "content/browser/compositor/image_transport_factory.h" #include "content/public/browser/context_factory.h" #include "ui/accelerated_widget_mac/accelerated_widget_mac.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" //////////////////////////////////////////////////////////////////////////////// // BrowserCompositorMac namespace content { namespace { // Set when no browser compositors should remain alive. bool g_has_shut_down = false; // The number of placeholder objects allocated. If this reaches zero, then // the BrowserCompositorMac being held on to for recycling, // |g_recyclable_browser_compositor|, will be freed. uint32_t g_placeholder_count = 0; // A spare BrowserCompositorMac kept around for recycling. base::LazyInstance> g_recyclable_browser_compositor; } // namespace BrowserCompositorMac::BrowserCompositorMac() : accelerated_widget_mac_(new ui::AcceleratedWidgetMac()), compositor_(content::GetContextFactory(), ui::WindowResizeHelperMac::Get()->task_runner()) { compositor_.SetAcceleratedWidget( accelerated_widget_mac_->accelerated_widget()); compositor_.SetLocksWillTimeOut(false); Suspend(); compositor_.AddObserver(this); } BrowserCompositorMac::~BrowserCompositorMac() { compositor_.RemoveObserver(this); } void BrowserCompositorMac::Suspend() { compositor_suspended_lock_ = compositor_.GetCompositorLock(); } void BrowserCompositorMac::Unsuspend() { compositor_suspended_lock_ = nullptr; } void BrowserCompositorMac::OnCompositingDidCommit( ui::Compositor* compositor_that_did_commit) { DCHECK_EQ(compositor_that_did_commit, compositor()); content::ImageTransportFactory::GetInstance() ->SetCompositorSuspendedForRecycle(compositor(), false); } // static scoped_ptr BrowserCompositorMac::Create() { DCHECK(ui::WindowResizeHelperMac::Get()->task_runner()); if (g_recyclable_browser_compositor.Get()) return std::move(g_recyclable_browser_compositor.Get()); return scoped_ptr(new BrowserCompositorMac); } // static void BrowserCompositorMac::Recycle( scoped_ptr compositor) { DCHECK(compositor); content::ImageTransportFactory::GetInstance() ->SetCompositorSuspendedForRecycle(compositor->compositor(), true); // It is an error to have a browser compositor continue to exist after // shutdown. CHECK(!g_has_shut_down); // Make this BrowserCompositorMac recyclable for future instances. g_recyclable_browser_compositor.Get().swap(compositor); // If there are no placeholders allocated, destroy the recyclable // BrowserCompositorMac that we just populated. if (!g_placeholder_count) g_recyclable_browser_compositor.Get().reset(); } // static void BrowserCompositorMac::DisableRecyclingForShutdown() { g_has_shut_down = true; g_recyclable_browser_compositor.Get().reset(); } //////////////////////////////////////////////////////////////////////////////// // BrowserCompositorMacPlaceholder BrowserCompositorMacPlaceholder::BrowserCompositorMacPlaceholder() { g_placeholder_count += 1; } BrowserCompositorMacPlaceholder::~BrowserCompositorMacPlaceholder() { DCHECK_GT(g_placeholder_count, 0u); g_placeholder_count -= 1; // If there are no placeholders allocated, destroy the recyclable // BrowserCompositorMac. if (!g_placeholder_count) g_recyclable_browser_compositor.Get().reset(); } } // namespace content