blob: 65f1326ef578307dffdbd8fc9e6f681f994848bf [file] [log] [blame]
// 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"
#import <Cocoa/Cocoa.h>
#include <stdint.h>
#include <utility>
#include "base/command_line.h"
#include "base/containers/circular_deque.h"
#include "base/lazy_instance.h"
#include "base/trace_event/trace_event.h"
#include "components/viz/common/features.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/renderer_host/display_util.h"
#include "content/public/browser/browser_thread.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"
#include "ui/base/layout.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/dip_util.h"
namespace content {
namespace {
// Weak pointers to all BrowserCompositorMac instances, used to
// - Determine if a spare RecyclableCompositorMac should be kept around (one
// should be only if there exists at least one BrowserCompositorMac).
// - Force all ui::Compositors to be destroyed at shut-down (because the NSView
// signals to shut down will come in very late, long after things that the
// ui::Compositor depend on have been destroyed).
// https://crbug.com/805726
base::LazyInstance<std::set<BrowserCompositorMac*>>::Leaky
g_browser_compositors;
// A spare RecyclableCompositorMac kept around for recycling.
base::LazyInstance<base::circular_deque<
std::unique_ptr<RecyclableCompositorMac>>>::DestructorAtExit
g_spare_recyclable_compositors;
void ReleaseSpareCompositors() {
// Allow at most one spare recyclable compositor.
while (g_spare_recyclable_compositors.Get().size() > 1)
g_spare_recyclable_compositors.Get().pop_front();
if (g_browser_compositors.Get().empty())
g_spare_recyclable_compositors.Get().clear();
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
// RecyclableCompositorMac
// A ui::Compositor and a gfx::AcceleratedWidget (and helper) that it draws
// into. This structure is used to efficiently recycle these structures across
// tabs (because creating a new ui::Compositor for each tab would be expensive
// in terms of time and resources).
class RecyclableCompositorMac : public ui::CompositorObserver {
public:
~RecyclableCompositorMac() override;
// Create a compositor, or recycle a preexisting one.
static std::unique_ptr<RecyclableCompositorMac> Create();
// Delete a compositor, or allow it to be recycled.
static void Recycle(std::unique_ptr<RecyclableCompositorMac> compositor);
ui::Compositor* compositor() { return &compositor_; }
ui::AcceleratedWidgetMac* accelerated_widget_mac() {
return accelerated_widget_mac_.get();
}
const gfx::Size pixel_size() const { return size_pixels_; }
float scale_factor() const { return scale_factor_; }
// Suspend will prevent the compositor from producing new frames. This should
// be called to avoid creating spurious frames while changing state.
// Compositors are created as suspended.
void Suspend();
void Unsuspend();
// Update the compositor's surface information, if needed.
void UpdateSurface(const gfx::Size& size_pixels, float scale_factor);
// Invalidate the compositor's surface information.
void InvalidateSurface();
// The viz::ParentLocalSurfaceIdAllocator for the ui::Compositor dispenses
// viz::LocalSurfaceIds that are renderered into by the ui::Compositor.
viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_;
gfx::Size size_pixels_;
float scale_factor_ = 1.f;
private:
RecyclableCompositorMac();
// ui::CompositorObserver implementation:
void OnCompositingDidCommit(ui::Compositor* compositor) override;
void OnCompositingStarted(ui::Compositor* compositor,
base::TimeTicks start_time) override {}
void OnCompositingEnded(ui::Compositor* compositor) override {}
void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
void OnCompositingChildResizing(ui::Compositor* compositor) override {}
void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
std::unique_ptr<ui::AcceleratedWidgetMac> accelerated_widget_mac_;
ui::Compositor compositor_;
std::unique_ptr<ui::CompositorLock> compositor_suspended_lock_;
DISALLOW_COPY_AND_ASSIGN(RecyclableCompositorMac);
};
RecyclableCompositorMac::RecyclableCompositorMac()
: accelerated_widget_mac_(new ui::AcceleratedWidgetMac()),
compositor_(content::GetContextFactoryPrivate()->AllocateFrameSinkId(),
content::GetContextFactory(),
content::GetContextFactoryPrivate(),
ui::WindowResizeHelperMac::Get()->task_runner(),
features::IsSurfaceSynchronizationEnabled(),
false /* enable_pixel_canvas */) {
compositor_.SetAcceleratedWidget(
accelerated_widget_mac_->accelerated_widget());
Suspend();
compositor_.AddObserver(this);
}
RecyclableCompositorMac::~RecyclableCompositorMac() {
compositor_.RemoveObserver(this);
}
void RecyclableCompositorMac::Suspend() {
// Requests a compositor lock without a timeout.
compositor_suspended_lock_ =
compositor_.GetCompositorLock(nullptr, base::TimeDelta());
}
void RecyclableCompositorMac::Unsuspend() {
compositor_suspended_lock_ = nullptr;
}
void RecyclableCompositorMac::UpdateSurface(const gfx::Size& size_pixels,
float scale_factor) {
if (size_pixels != size_pixels_ || scale_factor != scale_factor_) {
size_pixels_ = size_pixels;
scale_factor_ = scale_factor;
compositor()->SetScaleAndSize(scale_factor_, size_pixels_,
local_surface_id_allocator_.GenerateId());
}
}
void RecyclableCompositorMac::InvalidateSurface() {
size_pixels_ = gfx::Size();
scale_factor_ = 1.f;
local_surface_id_allocator_.Invalidate();
compositor()->SetScaleAndSize(
scale_factor_, size_pixels_,
local_surface_id_allocator_.GetCurrentLocalSurfaceId());
}
void RecyclableCompositorMac::OnCompositingDidCommit(
ui::Compositor* compositor_that_did_commit) {
DCHECK_EQ(compositor_that_did_commit, compositor());
accelerated_widget_mac_->SetSuspended(false);
}
// static
std::unique_ptr<RecyclableCompositorMac> RecyclableCompositorMac::Create() {
DCHECK(ui::WindowResizeHelperMac::Get()->task_runner());
if (!g_spare_recyclable_compositors.Get().empty()) {
std::unique_ptr<RecyclableCompositorMac> result;
result = std::move(g_spare_recyclable_compositors.Get().back());
g_spare_recyclable_compositors.Get().pop_back();
return result;
}
return std::unique_ptr<RecyclableCompositorMac>(new RecyclableCompositorMac);
}
// static
void RecyclableCompositorMac::Recycle(
std::unique_ptr<RecyclableCompositorMac> compositor) {
compositor->accelerated_widget_mac_->SetSuspended(true);
// Make this RecyclableCompositorMac recyclable for future instances.
g_spare_recyclable_compositors.Get().push_back(std::move(compositor));
// Post a task to free up the spare ui::Compositors when needed. Post this
// to the browser main thread so that we won't free any compositors while
// in a nested loop waiting to put up a new frame.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE, base::Bind(&ReleaseSpareCompositors));
}
////////////////////////////////////////////////////////////////////////////////
// BrowserCompositorMac
BrowserCompositorMac::BrowserCompositorMac(
ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view,
BrowserCompositorMacClient* client,
bool render_widget_host_is_hidden,
bool ns_view_attached_to_window,
const display::Display& initial_display,
const viz::FrameSinkId& frame_sink_id)
: client_(client),
accelerated_widget_mac_ns_view_(accelerated_widget_mac_ns_view),
dfh_display_(initial_display),
weak_factory_(this) {
g_browser_compositors.Get().insert(this);
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
// Ensure that this layer draws nothing when it does not not have delegated
// content (otherwise this solid color will be flashed during navigation).
root_layer_->SetColor(SK_ColorTRANSPARENT);
delegated_frame_host_.reset(new DelegatedFrameHost(
frame_sink_id, this,
base::FeatureList::IsEnabled(features::kVizDisplayCompositor),
true /* should_register_frame_sink_id */));
SetRenderWidgetHostIsHidden(render_widget_host_is_hidden);
SetNSViewAttachedToWindow(ns_view_attached_to_window);
}
BrowserCompositorMac::~BrowserCompositorMac() {
// Ensure that copy callbacks completed or cancelled during further tear-down
// do not call back into this.
weak_factory_.InvalidateWeakPtrs();
TransitionToState(HasNoCompositor);
delegated_frame_host_.reset();
root_layer_.reset();
size_t num_erased = g_browser_compositors.Get().erase(this);
DCHECK_EQ(1u, num_erased);
// If there are no compositors allocated, destroy the recyclable
// RecyclableCompositorMac.
if (g_browser_compositors.Get().empty())
g_spare_recyclable_compositors.Get().clear();
}
gfx::AcceleratedWidget BrowserCompositorMac::GetAcceleratedWidget() {
if (recyclable_compositor_) {
return recyclable_compositor_->accelerated_widget_mac()
->accelerated_widget();
}
return gfx::kNullAcceleratedWidget;
}
DelegatedFrameHost* BrowserCompositorMac::GetDelegatedFrameHost() {
DCHECK(delegated_frame_host_);
return delegated_frame_host_.get();
}
void BrowserCompositorMac::ClearCompositorFrame() {
// Make sure that we no longer hold a compositor lock by un-suspending the
// compositor. This ensures that we are able to swap in a new blank frame to
// replace any old content.
// https://crbug.com/739621
if (recyclable_compositor_)
recyclable_compositor_->Unsuspend();
if (delegated_frame_host_)
delegated_frame_host_->ClearDelegatedFrame();
}
bool BrowserCompositorMac::RequestRepaintForTesting() {
const viz::LocalSurfaceId& new_local_surface_id =
dfh_local_surface_id_allocator_.GenerateId();
delegated_frame_host_->EmbedSurface(
new_local_surface_id, dfh_size_dip_,
cc::DeadlinePolicy::UseExistingDeadline());
return client_->SynchronizeVisualProperties();
}
const gfx::CALayerParams* BrowserCompositorMac::GetLastCALayerParams() const {
if (!recyclable_compositor_)
return nullptr;
return recyclable_compositor_->accelerated_widget_mac()->GetCALayerParams();
}
viz::FrameSinkId BrowserCompositorMac::GetRootFrameSinkId() {
if (parent_ui_layer_)
return parent_ui_layer_->GetCompositor()->frame_sink_id();
if (recyclable_compositor_)
return recyclable_compositor_->compositor()->frame_sink_id();
return viz::FrameSinkId();
}
void BrowserCompositorMac::DidCreateNewRendererCompositorFrameSink(
viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink) {
renderer_compositor_frame_sink_ = renderer_compositor_frame_sink;
delegated_frame_host_->DidCreateNewRendererCompositorFrameSink(
renderer_compositor_frame_sink_);
}
void BrowserCompositorMac::OnDidNotProduceFrame(const viz::BeginFrameAck& ack) {
delegated_frame_host_->DidNotProduceFrame(ack);
}
void BrowserCompositorMac::SetBackgroundColor(SkColor background_color) {
background_color_ = background_color;
if (recyclable_compositor_)
recyclable_compositor_->compositor()->SetBackgroundColor(background_color_);
}
bool BrowserCompositorMac::UpdateNSViewAndDisplay(
const gfx::Size& new_size_dip,
const display::Display& new_display) {
if (new_size_dip == dfh_size_dip_ && new_display == dfh_display_)
return false;
bool needs_new_surface_id =
new_size_dip != dfh_size_dip_ ||
new_display.device_scale_factor() != dfh_display_.device_scale_factor();
dfh_display_ = new_display;
dfh_size_dip_ = new_size_dip;
dfh_size_pixels_ = gfx::ConvertSizeToPixel(dfh_display_.device_scale_factor(),
dfh_size_dip_);
root_layer_->SetBounds(gfx::Rect(dfh_size_dip_));
if (needs_new_surface_id) {
if (recyclable_compositor_)
recyclable_compositor_->Suspend();
GetDelegatedFrameHost()->EmbedSurface(
dfh_local_surface_id_allocator_.GenerateId(), dfh_size_dip_,
GetDeadlinePolicy());
}
if (recyclable_compositor_) {
recyclable_compositor_->compositor()->SetDisplayColorSpace(
dfh_display_.color_space());
recyclable_compositor_->UpdateSurface(dfh_size_pixels_,
dfh_display_.device_scale_factor());
}
return true;
}
void BrowserCompositorMac::SynchronizeVisualProperties(
float new_device_scale_factor,
const gfx::Size& new_size_in_pixels,
const viz::LocalSurfaceId& child_allocated_local_surface_id) {
if (dfh_local_surface_id_allocator_.UpdateFromChild(
child_allocated_local_surface_id)) {
dfh_display_.set_device_scale_factor(new_device_scale_factor);
dfh_size_dip_ = gfx::ConvertSizeToDIP(dfh_display_.device_scale_factor(),
new_size_in_pixels);
dfh_size_pixels_ = new_size_in_pixels;
root_layer_->SetBounds(gfx::Rect(dfh_size_dip_));
if (recyclable_compositor_) {
recyclable_compositor_->UpdateSurface(dfh_size_pixels_,
dfh_display_.device_scale_factor());
}
GetDelegatedFrameHost()->EmbedSurface(
dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
dfh_size_dip_, GetDeadlinePolicy());
}
client_->SynchronizeVisualProperties();
}
void BrowserCompositorMac::UpdateVSyncParameters(
const base::TimeTicks& timebase,
const base::TimeDelta& interval) {
if (recyclable_compositor_) {
recyclable_compositor_->compositor()->SetDisplayVSyncParameters(
timebase, interval);
}
}
void BrowserCompositorMac::SetRenderWidgetHostIsHidden(bool hidden) {
render_widget_host_is_hidden_ = hidden;
UpdateState();
}
void BrowserCompositorMac::SetNSViewAttachedToWindow(bool attached) {
ns_view_attached_to_window_ = attached;
UpdateState();
}
void BrowserCompositorMac::UpdateState() {
// Always use the parent ui::Layer's ui::Compositor if available.
if (parent_ui_layer_) {
TransitionToState(UseParentLayerCompositor);
return;
}
// If the host is visible and a compositor is required then create one.
if (!render_widget_host_is_hidden_) {
TransitionToState(HasAttachedCompositor);
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.
TransitionToState(HasNoCompositor);
}
void BrowserCompositorMac::TransitionToState(State new_state) {
// Note that the state enum values represent the other through which
// transitions must be done (see comments in State definition).
// Transition UseParentLayerCompositor -> HasNoCompositor.
if (state_ == UseParentLayerCompositor &&
new_state < UseParentLayerCompositor) {
DCHECK(root_layer_->parent());
root_layer_->parent()->RemoveObserver(this);
root_layer_->parent()->Remove(root_layer_.get());
delegated_frame_host_->WasHidden();
delegated_frame_host_->ResetCompositor();
state_ = HasNoCompositor;
}
// Transition HasNoCompositor -> HasDetachedCompositor.
if (state_ == HasNoCompositor && new_state < HasNoCompositor) {
recyclable_compositor_ = RecyclableCompositorMac::Create();
recyclable_compositor_->UpdateSurface(dfh_size_pixels_,
dfh_display_.device_scale_factor());
recyclable_compositor_->compositor()->SetRootLayer(root_layer_.get());
recyclable_compositor_->compositor()->SetBackgroundColor(background_color_);
recyclable_compositor_->compositor()->SetDisplayColorSpace(
dfh_display_.color_space());
recyclable_compositor_->accelerated_widget_mac()->SetNSView(
accelerated_widget_mac_ns_view_);
state_ = HasDetachedCompositor;
}
// Transition HasDetachedCompositor -> HasAttachedCompositor.
if (state_ == HasDetachedCompositor && new_state < HasDetachedCompositor) {
delegated_frame_host_->SetCompositor(recyclable_compositor_->compositor());
delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
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_->HasSavedFrame())
recyclable_compositor_->Unsuspend();
state_ = HasAttachedCompositor;
}
// Transition HasAttachedCompositor -> HasDetachedCompositor.
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
// necessary to remove all connections to its old ui::Compositor.
delegated_frame_host_->WasHidden();
delegated_frame_host_->ResetCompositor();
state_ = HasDetachedCompositor;
}
// Transition HasDetachedCompositor -> HasNoCompositor.
if (state_ == HasDetachedCompositor && new_state > HasDetachedCompositor) {
recyclable_compositor_->accelerated_widget_mac()->ResetNSView();
recyclable_compositor_->compositor()->SetRootLayer(nullptr);
recyclable_compositor_->InvalidateSurface();
RecyclableCompositorMac::Recycle(std::move(recyclable_compositor_));
state_ = HasNoCompositor;
}
// Transition HasNoCompositor -> UseParentLayerCompositor.
if (state_ == HasNoCompositor && new_state > HasNoCompositor) {
DCHECK(parent_ui_layer_);
DCHECK(parent_ui_layer_->GetCompositor());
DCHECK(!root_layer_->parent());
delegated_frame_host_->SetCompositor(parent_ui_layer_->GetCompositor());
delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_,
false /* record_presentation_time */);
parent_ui_layer_->Add(root_layer_.get());
parent_ui_layer_->AddObserver(this);
state_ = UseParentLayerCompositor;
}
}
// static
void BrowserCompositorMac::DisableRecyclingForShutdown() {
// 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();
}
void BrowserCompositorMac::SetNeedsBeginFrames(bool needs_begin_frames) {
delegated_frame_host_->SetNeedsBeginFrames(needs_begin_frames);
}
void BrowserCompositorMac::SetWantsAnimateOnlyBeginFrames() {
delegated_frame_host_->SetWantsAnimateOnlyBeginFrames();
}
void BrowserCompositorMac::TakeFallbackContentFrom(
BrowserCompositorMac* other) {
delegated_frame_host_->TakeFallbackContentFrom(
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);
}
}
////////////////////////////////////////////////////////////////////////////////
// DelegatedFrameHost, public:
ui::Layer* BrowserCompositorMac::DelegatedFrameHostGetLayer() const {
return root_layer_.get();
}
bool BrowserCompositorMac::DelegatedFrameHostIsVisible() const {
return state_ != HasNoCompositor;
}
SkColor BrowserCompositorMac::DelegatedFrameHostGetGutterColor() const {
return client_->BrowserCompositorMacGetGutterColor();
}
void BrowserCompositorMac::OnFirstSurfaceActivation(
const viz::SurfaceInfo& surface_info) {
if (!recyclable_compositor_)
return;
recyclable_compositor_->Unsuspend();
// Disable screen updates until the frame of the new size appears (because the
// content is drawn in the GPU process, it may change before we want it to).
if (repaint_state_ == RepaintState::Paused) {
bool compositor_is_nsview_size =
recyclable_compositor_->pixel_size() == dfh_size_pixels_ &&
recyclable_compositor_->scale_factor() ==
dfh_display_.device_scale_factor();
if (compositor_is_nsview_size || repaint_auto_resize_enabled_) {
NSDisableScreenUpdates();
repaint_state_ = RepaintState::ScreenUpdatesDisabled;
}
}
}
void BrowserCompositorMac::OnBeginFrame(base::TimeTicks frame_time) {
client_->BrowserCompositorMacOnBeginFrame(frame_time);
}
void BrowserCompositorMac::OnFrameTokenChanged(uint32_t frame_token) {
client_->OnFrameTokenChanged(frame_token);
}
void BrowserCompositorMac::DidNavigate() {
// The first navigation does not need a new LocalSurfaceID. The renderer can
// use the ID that was already provided.
if (!is_first_navigation_)
dfh_local_surface_id_allocator_.GenerateId();
const viz::LocalSurfaceId& local_surface_id =
dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
delegated_frame_host_->EmbedSurface(
local_surface_id, dfh_size_dip_,
cc::DeadlinePolicy::UseExistingDeadline());
client_->SynchronizeVisualProperties();
delegated_frame_host_->DidNavigate();
is_first_navigation_ = false;
}
void BrowserCompositorMac::DidReceiveFirstFrameAfterNavigation() {
client_->DidReceiveFirstFrameAfterNavigation();
}
void BrowserCompositorMac::BeginPauseForFrame(bool auto_resize_enabled) {
repaint_auto_resize_enabled_ = auto_resize_enabled;
repaint_state_ = RepaintState::Paused;
}
void BrowserCompositorMac::EndPauseForFrame() {
if (repaint_state_ == RepaintState::ScreenUpdatesDisabled)
NSEnableScreenUpdates();
repaint_state_ = RepaintState::None;
}
bool BrowserCompositorMac::ShouldContinueToPauseForFrame() const {
if (state_ == UseParentLayerCompositor)
return false;
// The renderer won't produce a frame if its frame sink hasn't been created
// yet.
if (!renderer_compositor_frame_sink_)
return false;
if (!recyclable_compositor_)
return false;
return !recyclable_compositor_->accelerated_widget_mac()->HasFrameOfSize(
dfh_size_dip_);
}
void BrowserCompositorMac::SetParentUiLayer(ui::Layer* new_parent_ui_layer) {
if (new_parent_ui_layer) {
DCHECK(new_parent_ui_layer->GetCompositor());
DCHECK(!parent_ui_layer_);
parent_ui_layer_ = new_parent_ui_layer;
} else if (parent_ui_layer_) {
DCHECK(root_layer_->parent());
DCHECK_EQ(root_layer_->parent(), parent_ui_layer_);
parent_ui_layer_ = nullptr;
}
UpdateState();
}
bool BrowserCompositorMac::ForceNewSurfaceForTesting() {
display::Display new_display(dfh_display_);
new_display.set_device_scale_factor(new_display.device_scale_factor() * 2.0f);
return UpdateNSViewAndDisplay(dfh_size_dip_, new_display);
}
void BrowserCompositorMac::GetRendererScreenInfo(
ScreenInfo* screen_info) const {
DisplayUtil::DisplayToScreenInfo(screen_info, dfh_display_);
}
viz::ScopedSurfaceIdAllocator
BrowserCompositorMac::GetScopedRendererSurfaceIdAllocator(
base::OnceCallback<void()> allocation_task) {
return viz::ScopedSurfaceIdAllocator(&dfh_local_surface_id_allocator_,
std::move(allocation_task));
}
const viz::LocalSurfaceId& BrowserCompositorMac::GetRendererLocalSurfaceId() {
if (dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceId().is_valid())
return dfh_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
return dfh_local_surface_id_allocator_.GenerateId();
}
bool BrowserCompositorMac::UpdateRendererLocalSurfaceIdFromChild(
const viz::LocalSurfaceId& child_allocated_local_surface_id) {
return dfh_local_surface_id_allocator_.UpdateFromChild(
child_allocated_local_surface_id);
}
void BrowserCompositorMac::LayerDestroyed(ui::Layer* layer) {
DCHECK_EQ(layer, parent_ui_layer_);
SetParentUiLayer(nullptr);
}
ui::Compositor* BrowserCompositorMac::GetCompositorForTesting() const {
if (recyclable_compositor_)
return recyclable_compositor_->compositor();
return nullptr;
}
cc::DeadlinePolicy BrowserCompositorMac::GetDeadlinePolicy() const {
// Determined empirically for smoothness.
uint32_t frames_to_wait = 8;
// When using the RecyclableCompositor, never wait for frames to arrive
// (surface sync is managed by the Suspend/Unsuspend lock).
if (recyclable_compositor_)
frames_to_wait = 0;
return cc::DeadlinePolicy::UseSpecifiedDeadline(frames_to_wait);
}
} // namespace content