Commit 1b6d6cec authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

MacViews: Enable compositor recycling

We create a new ui::Compositor at the first character typed in the
omnibox. This is very expensive, and is compounded by the fact that the
shaders used by rasterization and display must be re-created in this
new context.

There already exists ui::Compositor recycling in content:: for
RenderWidgetHostViewMac. Move this code to ui::, and share it with
BridgedNativeWidget.

Bug: 712268
Change-Id: I969174e2c38b181e18a10e78dd49d3e9be9690e5
Reviewed-on: https://chromium-review.googlesource.com/1132710
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarLeonard Grey <lgrey@chromium.org>
Cr-Commit-Position: refs/heads/master@{#574738}
parent caf225a5
......@@ -20,12 +20,11 @@
namespace ui {
class AcceleratedWidgetMacNSView;
class RecyclableCompositorMac;
}
namespace content {
class RecyclableCompositorMac;
class BrowserCompositorMacClient {
public:
virtual SkColor BrowserCompositorMacGetGutterColor() const = 0;
......@@ -203,7 +202,7 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
BrowserCompositorMacClient* client_ = nullptr;
ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view_ = nullptr;
std::unique_ptr<RecyclableCompositorMac> recyclable_compositor_;
std::unique_ptr<ui::RecyclableCompositorMac> recyclable_compositor_;
std::unique_ptr<DelegatedFrameHost> delegated_frame_host_;
std::unique_ptr<ui::Layer> root_layer_;
......
......@@ -20,6 +20,7 @@
#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/compositor/recyclable_compositor_mac.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/dip_util.h"
......@@ -37,162 +38,8 @@ namespace {
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
......@@ -233,11 +80,6 @@ BrowserCompositorMac::~BrowserCompositorMac() {
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();
}
DelegatedFrameHost* BrowserCompositorMac::GetDelegatedFrameHost() {
......@@ -268,7 +110,7 @@ bool BrowserCompositorMac::RequestRepaintForTesting() {
const gfx::CALayerParams* BrowserCompositorMac::GetLastCALayerParams() const {
if (!recyclable_compositor_)
return nullptr;
return recyclable_compositor_->accelerated_widget_mac()->GetCALayerParams();
return recyclable_compositor_->widget()->GetCALayerParams();
}
viz::FrameSinkId BrowserCompositorMac::GetRootFrameSinkId() {
......@@ -417,14 +259,16 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
// Transition HasNoCompositor -> HasDetachedCompositor.
if (state_ == HasNoCompositor && new_state < HasNoCompositor) {
recyclable_compositor_ = RecyclableCompositorMac::Create();
recyclable_compositor_ =
ui::RecyclableCompositorMacFactory::Get()->CreateCompositor(
content::GetContextFactory(), content::GetContextFactoryPrivate());
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(
recyclable_compositor_->widget()->SetNSView(
accelerated_widget_mac_ns_view_);
state_ = HasDetachedCompositor;
}
......@@ -458,10 +302,11 @@ void BrowserCompositorMac::TransitionToState(State new_state) {
// Transition HasDetachedCompositor -> HasNoCompositor.
if (state_ == HasDetachedCompositor && new_state > HasDetachedCompositor) {
recyclable_compositor_->accelerated_widget_mac()->ResetNSView();
recyclable_compositor_->widget()->ResetNSView();
recyclable_compositor_->compositor()->SetRootLayer(nullptr);
recyclable_compositor_->InvalidateSurface();
RecyclableCompositorMac::Recycle(std::move(recyclable_compositor_));
ui::RecyclableCompositorMacFactory::Get()->RecycleCompositor(
std::move(recyclable_compositor_));
state_ = HasNoCompositor;
}
......@@ -489,7 +334,8 @@ void BrowserCompositorMac::DisableRecyclingForShutdown() {
*g_browser_compositors.Get().begin();
browser_compositor->client_->DestroyCompositorForShutdown();
}
g_spare_recyclable_compositors.Get().clear();
ui::RecyclableCompositorMacFactory::Get()->DisableRecyclingForShutdown();
}
void BrowserCompositorMac::SetNeedsBeginFrames(bool needs_begin_frames) {
......@@ -574,8 +420,7 @@ bool BrowserCompositorMac::ShouldContinueToPauseForFrame() const {
if (!recyclable_compositor_)
return false;
return !recyclable_compositor_->accelerated_widget_mac()->HasFrameOfSize(
dfh_size_dip_);
return !recyclable_compositor_->widget()->HasFrameOfSize(dfh_size_dip_);
}
void BrowserCompositorMac::SetParentUiLayer(ui::Layer* new_parent_ui_layer) {
......
......@@ -67,6 +67,8 @@ jumbo_component("compositor") {
"paint_recorder.cc",
"paint_recorder.h",
"property_change_reason.h",
"recyclable_compositor_mac.cc",
"recyclable_compositor_mac.h",
"reflector.cc",
"reflector.h",
"scoped_animation_duration_scale_mode.cc",
......@@ -102,6 +104,10 @@ jumbo_component("compositor") {
"//ui/gl",
]
if (is_mac) {
deps += [ "//ui/accelerated_widget_mac" ]
}
if (is_win && use_aura) {
# TODO(sky): before we make this real need to remove
# IDR_BITMAP_BRUSH_IMAGE.
......
......@@ -9,6 +9,7 @@ include_rules = [
"+third_party/khronos/GLES2/gl2.h",
"+third_party/skia",
"+ui/base",
"+ui/accelerated_widget_mac",
"+ui/display/display_switches.h",
"+ui/gfx",
"+ui/gl",
......
// Copyright 2018 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 "ui/compositor/recyclable_compositor_mac.h"
#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/viz/common/features.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/compositor_switches.h"
namespace ui {
namespace {
// Returns a task runner for creating a ui::Compositor. This allows compositor
// tasks to be funneled through ui::WindowResizeHelper's task runner to allow
// resize operations to coordinate with frames provided by the GPU process.
scoped_refptr<base::SingleThreadTaskRunner> GetCompositorTaskRunner() {
// If the WindowResizeHelper's pumpable task runner is set, it means the GPU
// process is directing messages there, and the compositor can synchronize
// with it. Otherwise, just use the UI thread.
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
ui::WindowResizeHelperMac::Get()->task_runner();
return task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get();
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
// RecyclableCompositorMac
RecyclableCompositorMac::RecyclableCompositorMac(
ui::ContextFactory* context_factory,
ui::ContextFactoryPrivate* context_factory_private)
: accelerated_widget_mac_(new ui::AcceleratedWidgetMac()),
compositor_(context_factory_private->AllocateFrameSinkId(),
context_factory,
context_factory_private,
GetCompositorTaskRunner(),
features::IsSurfaceSynchronizationEnabled(),
ui::IsPixelCanvasRecordingEnabled()) {
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);
}
////////////////////////////////////////////////////////////////////////////////
// RecyclableCompositorMacFactory
// static
RecyclableCompositorMacFactory* RecyclableCompositorMacFactory::Get() {
static base::NoDestructor<RecyclableCompositorMacFactory> factory;
return factory.get();
}
std::unique_ptr<RecyclableCompositorMac>
RecyclableCompositorMacFactory::CreateCompositor(
ui::ContextFactory* context_factory,
ui::ContextFactoryPrivate* context_factory_private) {
active_compositor_count_ += 1;
if (!compositors_.empty()) {
std::unique_ptr<RecyclableCompositorMac> result;
result = std::move(compositors_.back());
compositors_.pop_back();
return result;
}
return std::make_unique<RecyclableCompositorMac>(context_factory,
context_factory_private);
}
void RecyclableCompositorMacFactory::RecycleCompositor(
std::unique_ptr<RecyclableCompositorMac> compositor) {
// When we get to zero compositors in use, destroy all spare compositors.
// This is done to appease tests that rely on compositors being destroyed
// immediately (if the compositor is recycled and continues to exist, its
// subsequent initialization will crash).
active_compositor_count_ -= 1;
if (!active_compositor_count_) {
compositors_.clear();
return;
}
if (recycling_disabled_)
return;
compositor->accelerated_widget_mac_->SetSuspended(true);
// Make this RecyclableCompositorMac recyclable for future instances.
compositors_.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.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&RecyclableCompositorMacFactory::ReduceSpareCompositors,
weak_factory_.GetWeakPtr()));
}
RecyclableCompositorMacFactory::RecyclableCompositorMacFactory()
: weak_factory_(this) {}
RecyclableCompositorMacFactory::~RecyclableCompositorMacFactory() = default;
void RecyclableCompositorMacFactory::ReduceSpareCompositors() {
// Allow at most one spare recyclable compositor.
while (compositors_.size() > 1)
compositors_.pop_front();
}
void RecyclableCompositorMacFactory::DisableRecyclingForShutdown() {
recycling_disabled_ = true;
compositors_.clear();
}
} // namespace ui
// Copyright 2018 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.
#ifndef UI_COMPOSITOR_RECYCLABLE_COMPOSITOR_MAC_H_
#define UI_COMPOSITOR_RECYCLABLE_COMPOSITOR_MAC_H_
#include "base/no_destructor.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_export.h"
#include "ui/compositor/compositor_observer.h"
namespace ui {
////////////////////////////////////////////////////////////////////////////////
// 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 COMPOSITOR_EXPORT RecyclableCompositorMac
: public ui::CompositorObserver {
public:
RecyclableCompositorMac(ui::ContextFactory* context_factory,
ui::ContextFactoryPrivate* context_factory_private);
~RecyclableCompositorMac() override;
ui::Compositor* compositor() { return &compositor_; }
ui::AcceleratedWidgetMac* widget() { 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:
friend class RecyclableCompositorMacFactory;
// 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);
};
////////////////////////////////////////////////////////////////////////////////
// RecyclableCompositorMacFactory
//
// The factory through which RecyclableCompositorMacs are created and recycled.
class COMPOSITOR_EXPORT RecyclableCompositorMacFactory {
public:
static RecyclableCompositorMacFactory* Get();
// Create a compositor, or recycle a preexisting one.
std::unique_ptr<RecyclableCompositorMac> CreateCompositor(
ui::ContextFactory* context_factory,
ui::ContextFactoryPrivate* context_factory_private);
// Delete a compositor, or allow it to be recycled.
void RecycleCompositor(std::unique_ptr<RecyclableCompositorMac> compositor);
// Destroy any compositors that are being kept around for recycling.
void DisableRecyclingForShutdown();
private:
friend class base::NoDestructor<ui::RecyclableCompositorMacFactory>;
RecyclableCompositorMacFactory();
~RecyclableCompositorMacFactory();
void ReduceSpareCompositors();
// The number of RecyclableCompositors that have been vended out and have
// not yet been recycled.
size_t active_compositor_count_ = 0;
bool recycling_disabled_ = false;
std::list<std::unique_ptr<RecyclableCompositorMac>> compositors_;
base::WeakPtrFactory<RecyclableCompositorMacFactory> weak_factory_;
};
} // namespace ui
#endif // UI_COMPOSITOR_RECYCLABLE_COMPOSITOR_MAC_H_
......@@ -31,6 +31,7 @@
namespace ui {
class InputMethod;
class RecyclableCompositorMac;
}
namespace views {
......@@ -309,12 +310,8 @@ class VIEWS_EXPORT BridgedNativeWidget
std::vector<BridgedNativeWidget*> child_windows_;
base::scoped_nsobject<NSView> compositor_superview_;
std::unique_ptr<ui::AcceleratedWidgetMac> compositor_widget_;
std::unique_ptr<ui::DisplayCALayerTree> display_ca_layer_tree_;
std::unique_ptr<ui::Compositor> compositor_;
std::unique_ptr<ui::CompositorLock> compositor_lock_;
viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_;
std::unique_ptr<ui::RecyclableCompositorMac> compositor_;
// Tracks the bounds when the window last started entering fullscreen. Used to
// provide an answer for GetRestoredBounds(), but not ever sent to Cocoa (it
......
......@@ -13,7 +13,6 @@
#include "base/mac/mac_util.h"
#import "base/mac/sdk_forward_declarations.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/viz/common/features.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
......@@ -22,7 +21,7 @@
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/input_method_factory.h"
#include "ui/base/layout.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/compositor/recyclable_compositor_mac.h"
#include "ui/gfx/geometry/dip_util.h"
#import "ui/gfx/mac/coordinate_conversion.h"
#import "ui/gfx/mac/nswindow_frame_controls.h"
......@@ -171,18 +170,6 @@ gfx::Size GetClientSizeForWindowSize(NSWindow* window,
return gfx::Size([window contentRectForFrameRect:frame_rect].size);
}
// Returns a task runner for creating a ui::Compositor. This allows compositor
// tasks to be funneled through ui::WindowResizeHelper's task runner to allow
// resize operations to coordinate with frames provided by the GPU process.
scoped_refptr<base::SingleThreadTaskRunner> GetCompositorTaskRunner() {
// If the WindowResizeHelper's pumpable task runner is set, it means the GPU
// process is directing messages there, and the compositor can synchronize
// with it. Otherwise, just use the UI thread.
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
ui::WindowResizeHelperMac::Get()->task_runner();
return task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get();
}
void RankNSViews(views::View* view,
const views::BridgedNativeWidget::AssociatedViews& hosts,
RankMap* rank) {
......@@ -452,7 +439,7 @@ void BridgedNativeWidget::SetRootView(views::View* view) {
// If this is ever false, the compositor will need to be properly torn down
// and replaced, pointing at the new view.
DCHECK(!view || !compositor_widget_);
DCHECK(!view || !compositor_);
drag_drop_client_.reset();
[bridged_view_ clearView];
......@@ -1003,8 +990,8 @@ void BridgedNativeWidget::ReparentNativeView(NSView* native_view,
bool BridgedNativeWidget::ShouldWaitInPreCommit() {
return window_visible_ &&
(!compositor_widget_ ||
!compositor_widget_->HasFrameOfSize(GetClientAreaSize()));
(!compositor_ ||
!compositor_->widget()->HasFrameOfSize(GetClientAreaSize()));
}
base::TimeDelta BridgedNativeWidget::PreCommitTimeout() {
......@@ -1079,13 +1066,13 @@ void BridgedNativeWidget::OnDeviceScaleFactorChanged(
void BridgedNativeWidget::AcceleratedWidgetCALayerParamsUpdated() {
// Ignore frames arriving "late" for an old size. A frame at the new size
// should arrive soon.
if (!compositor_widget_->HasFrameOfSize(GetClientAreaSize()))
if (!compositor_->widget()->HasFrameOfSize(GetClientAreaSize()))
return;
// Update the DisplayCALayerTree with the most recent CALayerParams, to make
// the content display on-screen.
const gfx::CALayerParams* ca_layer_params =
compositor_widget_->GetCALayerParams();
compositor_->widget()->GetCALayerParams();
if (ca_layer_params)
display_ca_layer_tree_->UpdateCALayerTree(*ca_layer_params);
......@@ -1212,7 +1199,6 @@ gfx::Size BridgedNativeWidget::GetClientAreaSize() const {
void BridgedNativeWidget::CreateCompositor() {
DCHECK(!compositor_);
DCHECK(!compositor_widget_);
DCHECK(ViewsDelegate::GetInstance());
ui::ContextFactory* context_factory =
......@@ -1223,24 +1209,20 @@ void BridgedNativeWidget::CreateCompositor() {
AddCompositorSuperview();
compositor_widget_.reset(new ui::AcceleratedWidgetMac());
compositor_.reset(new ui::Compositor(
context_factory_private->AllocateFrameSinkId(), context_factory,
context_factory_private, GetCompositorTaskRunner(),
features::IsSurfaceSynchronizationEnabled(),
ui::IsPixelCanvasRecordingEnabled()));
compositor_->SetAcceleratedWidget(compositor_widget_->accelerated_widget());
compositor_widget_->SetNSView(this);
compositor_ = ui::RecyclableCompositorMacFactory::Get()->CreateCompositor(
context_factory, context_factory_private);
compositor_->widget()->SetNSView(this);
}
void BridgedNativeWidget::InitCompositor() {
TRACE_EVENT0("ui", "BridgedNativeWidget::InitCompositor");
DCHECK(layer());
float scale_factor = GetDeviceScaleFactorFromView(compositor_superview_);
gfx::Size size_in_dip = GetClientAreaSize();
compositor_->SetScaleAndSize(scale_factor,
ConvertSizeToPixel(scale_factor, size_in_dip),
parent_local_surface_id_allocator_.GenerateId());
compositor_->SetRootLayer(layer());
compositor_->UpdateSurface(ConvertSizeToPixel(scale_factor, size_in_dip),
scale_factor);
compositor_->compositor()->SetRootLayer(layer());
compositor_->Unsuspend();
}
void BridgedNativeWidget::DestroyCompositor() {
......@@ -1255,13 +1237,12 @@ void BridgedNativeWidget::DestroyCompositor() {
}
DestroyLayer();
if (!compositor_widget_) {
DCHECK(!compositor_);
if (!compositor_)
return;
}
compositor_widget_->ResetNSView();
compositor_.reset();
compositor_widget_.reset();
compositor_->widget()->ResetNSView();
compositor_->compositor()->SetRootLayer(nullptr);
ui::RecyclableCompositorMacFactory::Get()->RecycleCompositor(
std::move(compositor_));
}
void BridgedNativeWidget::AddCompositorSuperview() {
......@@ -1303,13 +1284,7 @@ void BridgedNativeWidget::UpdateLayerProperties() {
ui::CATransactionCoordinator::Get().Synchronize();
layer()->SetBounds(gfx::Rect(size_in_dip));
if (compositor_->size() != size_in_pixel ||
compositor_->device_scale_factor() != scale_factor) {
compositor_->SetScaleAndSize(
scale_factor, size_in_pixel,
parent_local_surface_id_allocator_.GenerateId());
}
compositor_->UpdateSurface(size_in_pixel, scale_factor);
// For a translucent window, the shadow calculation needs to be carried out
// after the frame from the compositor arrives.
......@@ -1319,8 +1294,7 @@ void BridgedNativeWidget::UpdateLayerProperties() {
void BridgedNativeWidget::MaybeWaitForFrame(const gfx::Size& size_in_dip) {
return; // TODO(https://crbug.com/682825): Delete this during cleanup.
if (!layer()->IsDrawn() || compositor_widget_->HasFrameOfSize(size_in_dip))
if (!layer()->IsDrawn() || compositor_->widget()->HasFrameOfSize(size_in_dip))
return;
const int kPaintMsgTimeoutMS = 50;
......@@ -1336,7 +1310,7 @@ void BridgedNativeWidget::MaybeWaitForFrame(const gfx::Size& size_in_dip) {
// Since the UI thread is blocked, the size shouldn't change.
DCHECK(size_in_dip == GetClientAreaSize());
if (compositor_widget_->HasFrameOfSize(size_in_dip))
if (compositor_->widget()->HasFrameOfSize(size_in_dip))
return; // Frame arrived.
}
}
......@@ -1377,14 +1351,10 @@ NSMutableDictionary* BridgedNativeWidget::GetWindowProperties() const {
void BridgedNativeWidget::UpdateLayerVisibility() {
layer()->SetVisible(window_visible_);
if (window_visible_) {
compositor_lock_.reset();
} else if (!compositor_lock_) {
// Assume that GetCompositorLock always succeeds (if it does not, then a
// flicker may be seen).
compositor_lock_ =
compositor_->GetCompositorLock(nullptr, base::TimeDelta());
}
if (window_visible_)
compositor_->Unsuspend();
else
compositor_->Suspend();
}
} // namespace views
......@@ -23,6 +23,7 @@
#import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
#import "ui/base/cocoa/window_size_constants.h"
#import "ui/base/test/scoped_fake_full_keyboard_access.h"
#include "ui/compositor/recyclable_compositor_mac.h"
#import "ui/events/test/cocoa_test_event_utils.h"
#include "ui/events/test/event_generator.h"
#import "ui/gfx/mac/coordinate_conversion.h"
......@@ -102,7 +103,7 @@ class BridgedNativeWidgetTestApi {
const float kScaleFactor = 1.0f;
ui::CALayerFrameSink* ca_layer_frame_sink =
ui::CALayerFrameSink::FromAcceleratedWidget(
bridge_->compositor_widget_->accelerated_widget());
bridge_->compositor_->widget()->accelerated_widget());
gfx::CALayerParams ca_layer_params;
ca_layer_params.is_empty = false;
ca_layer_params.pixel_size = size;
......
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