|  | // 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/renderer_host/browser_compositor_view_mac.h" | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <utility> | 
|  |  | 
|  | #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<std::unique_ptr<BrowserCompositorMac>> | 
|  | 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 | 
|  | std::unique_ptr<BrowserCompositorMac> BrowserCompositorMac::Create() { | 
|  | DCHECK(ui::WindowResizeHelperMac::Get()->task_runner()); | 
|  | if (g_recyclable_browser_compositor.Get()) | 
|  | return std::move(g_recyclable_browser_compositor.Get()); | 
|  | return std::unique_ptr<BrowserCompositorMac>(new BrowserCompositorMac); | 
|  | } | 
|  |  | 
|  | // static | 
|  | void BrowserCompositorMac::Recycle( | 
|  | std::unique_ptr<BrowserCompositorMac> 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 |