Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(688)

Unified Diff: content/browser/renderer_host/browser_compositor_view_mac.mm

Issue 2093113003: Clean up the RWHVMac to ui::Compositor interface (phase 1 of 2) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove hack Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/browser_compositor_view_mac.mm
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm
index 6002eca17dc044010211bc2c24725c9c4a24e702..e9faa0a9b76ee4e1120dcdd1f8d0c6b9809563ac 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -14,9 +14,8 @@
#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
+#include "ui/base/layout.h"
+#include "ui/gfx/geometry/dip_util.h"
namespace content {
@@ -26,17 +25,68 @@
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;
+// the RecyclableCompositorMac being held on to for recycling,
+// |g_spare_recyclable_compositor|, will be freed.
+uint32_t g_browser_compositor_count = 0;
-// A spare BrowserCompositorMac kept around for recycling.
-base::LazyInstance<std::unique_ptr<BrowserCompositorMac>>
- g_recyclable_browser_compositor;
+// A spare RecyclableCompositorMac kept around for recycling.
+base::LazyInstance<std::unique_ptr<RecyclableCompositorMac>>
+ g_spare_recyclable_compositor;
} // namespace
-BrowserCompositorMac::BrowserCompositorMac()
+////////////////////////////////////////////////////////////////////////////////
+// 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:
+ virtual ~RecyclableCompositorMac();
+
+ // 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);
+
+ // Indicate that the recyclable compositor should be destroyed, and no future
+ // compositors should be recycled.
+ static void DisableRecyclingForShutdown();
+
+ ui::Compositor* compositor() { return &compositor_; }
+ ui::AcceleratedWidgetMac* accelerated_widget_mac() {
+ return accelerated_widget_mac_.get();
+ }
+
+ // 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();
+
+ 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 OnCompositingAborted(ui::Compositor* compositor) override {}
+ void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
+ void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
+
+ std::unique_ptr<ui::AcceleratedWidgetMac> accelerated_widget_mac_;
+ ui::Compositor compositor_;
+ scoped_refptr<ui::CompositorLock> compositor_suspended_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(RecyclableCompositorMac);
+};
+
+RecyclableCompositorMac::RecyclableCompositorMac()
: accelerated_widget_mac_(new ui::AcceleratedWidgetMac()),
compositor_(content::GetContextFactory(),
ui::WindowResizeHelperMac::Get()->task_runner()) {
@@ -47,19 +97,19 @@
compositor_.AddObserver(this);
}
-BrowserCompositorMac::~BrowserCompositorMac() {
+RecyclableCompositorMac::~RecyclableCompositorMac() {
compositor_.RemoveObserver(this);
}
-void BrowserCompositorMac::Suspend() {
+void RecyclableCompositorMac::Suspend() {
compositor_suspended_lock_ = compositor_.GetCompositorLock();
}
-void BrowserCompositorMac::Unsuspend() {
+void RecyclableCompositorMac::Unsuspend() {
compositor_suspended_lock_ = nullptr;
}
-void BrowserCompositorMac::OnCompositingDidCommit(
+void RecyclableCompositorMac::OnCompositingDidCommit(
ui::Compositor* compositor_that_did_commit) {
DCHECK_EQ(compositor_that_did_commit, compositor());
content::ImageTransportFactory::GetInstance()
@@ -67,16 +117,16 @@
}
// static
-std::unique_ptr<BrowserCompositorMac> BrowserCompositorMac::Create() {
+std::unique_ptr<RecyclableCompositorMac> RecyclableCompositorMac::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);
+ if (g_spare_recyclable_compositor.Get())
+ return std::move(g_spare_recyclable_compositor.Get());
+ return std::unique_ptr<RecyclableCompositorMac>(new RecyclableCompositorMac);
}
// static
-void BrowserCompositorMac::Recycle(
- std::unique_ptr<BrowserCompositorMac> compositor) {
+void RecyclableCompositorMac::Recycle(
+ std::unique_ptr<RecyclableCompositorMac> compositor) {
DCHECK(compositor);
content::ImageTransportFactory::GetInstance()
->SetCompositorSuspendedForRecycle(compositor->compositor(), true);
@@ -85,36 +135,249 @@
// shutdown.
CHECK(!g_has_shut_down);
- // Make this BrowserCompositorMac recyclable for future instances.
- g_recyclable_browser_compositor.Get().swap(compositor);
+ // Make this RecyclableCompositorMac recyclable for future instances.
+ g_spare_recyclable_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();
+ // RecyclableCompositorMac that we just populated.
+ if (!g_browser_compositor_count)
+ g_spare_recyclable_compositor.Get().reset();
}
-// static
-void BrowserCompositorMac::DisableRecyclingForShutdown() {
- g_has_shut_down = true;
- g_recyclable_browser_compositor.Get().reset();
+////////////////////////////////////////////////////////////////////////////////
+// BrowserCompositorMac
+
+BrowserCompositorMac::BrowserCompositorMac(
+ ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view,
+ DelegatedFrameHostClient* delegated_frame_host_client,
+ bool render_widget_host_is_hidden,
+ bool ns_view_attached_to_window)
+ : accelerated_widget_mac_ns_view_(accelerated_widget_mac_ns_view),
+ weak_factory_(this) {
+ g_browser_compositor_count += 1;
+
+ root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
+ delegated_frame_host_.reset(
+ new DelegatedFrameHost(delegated_frame_host_client));
+
+ SetRenderWidgetHostIsHidden(render_widget_host_is_hidden);
+ SetNSViewAttachedToWindow(ns_view_attached_to_window);
}
-////////////////////////////////////////////////////////////////////////////////
-// BrowserCompositorMacPlaceholder
+BrowserCompositorMac::~BrowserCompositorMac() {
+ DCHECK(has_been_destroyed_);
+}
-BrowserCompositorMacPlaceholder::BrowserCompositorMacPlaceholder() {
- g_placeholder_count += 1;
+void BrowserCompositorMac::Destroy() {
+ if (has_been_destroyed_)
+ return;
+
+ TransitionToState(HasNoCompositor);
+ delegated_frame_host_.reset();
+ root_layer_.reset();
+ has_been_destroyed_ = true;
+
+ DCHECK_GT(g_browser_compositor_count, 0u);
+ g_browser_compositor_count -= 1;
+
+ // If there are no compositors allocated, destroy the recyclable
+ // RecyclableCompositorMac.
+ if (!g_browser_compositor_count)
+ g_spare_recyclable_compositor.Get().reset();
+}
+
+ui::AcceleratedWidgetMac* BrowserCompositorMac::GetAcceleratedWidgetMac() {
+ if (recyclable_compositor_)
+ return recyclable_compositor_->accelerated_widget_mac();
+ return nullptr;
}
-BrowserCompositorMacPlaceholder::~BrowserCompositorMacPlaceholder() {
- DCHECK_GT(g_placeholder_count, 0u);
- g_placeholder_count -= 1;
+ui::Layer* BrowserCompositorMac::GetRootLayer() {
+ return root_layer_.get();
+}
- // If there are no placeholders allocated, destroy the recyclable
- // BrowserCompositorMac.
- if (!g_placeholder_count)
- g_recyclable_browser_compositor.Get().reset();
+DelegatedFrameHost* BrowserCompositorMac::GetDelegatedFrameHost() {
+ DCHECK(delegated_frame_host_);
+ return delegated_frame_host_.get();
+}
+
+void BrowserCompositorMac::CopyCompleted(
+ base::WeakPtr<BrowserCompositorMac> browser_compositor,
+ const ReadbackRequestCallback& callback,
+ const SkBitmap& bitmap,
+ ReadbackResponse response) {
+ callback.Run(bitmap, response);
+ if (browser_compositor) {
+ browser_compositor->outstanding_copy_count_ -= 1;
+ browser_compositor->UpdateState();
+ }
+}
+
+void BrowserCompositorMac::CopyFromCompositingSurface(
+ const gfx::Rect& src_subrect,
+ const gfx::Size& dst_size,
+ const ReadbackRequestCallback& callback,
+ SkColorType preferred_color_type) {
+ DCHECK(delegated_frame_host_);
+ DCHECK(state_ == HasAttachedCompositor);
+ outstanding_copy_count_ += 1;
+
+ auto callback_with_decrement =
+ base::Bind(&BrowserCompositorMac::CopyCompleted,
+ weak_factory_.GetWeakPtr(), callback);
+ delegated_frame_host_->CopyFromCompositingSurface(
+ src_subrect, dst_size, callback_with_decrement, preferred_color_type);
+}
+
+void BrowserCompositorMac::CopyToVideoFrameCompleted(
+ base::WeakPtr<BrowserCompositorMac> browser_compositor,
+ const base::Callback<void(const gfx::Rect&, bool)>& callback,
+ const gfx::Rect& rect,
+ bool result) {
+ callback.Run(rect, result);
+ if (browser_compositor) {
+ browser_compositor->outstanding_copy_count_ -= 1;
+ browser_compositor->UpdateState();
+ }
+}
+
+void BrowserCompositorMac::CopyFromCompositingSurfaceToVideoFrame(
+ const gfx::Rect& src_subrect,
+ const scoped_refptr<media::VideoFrame>& target,
+ const base::Callback<void(const gfx::Rect&, bool)>& callback) {
+ DCHECK(delegated_frame_host_);
+ DCHECK(state_ == HasAttachedCompositor);
+ outstanding_copy_count_ += 1;
+
+ auto callback_with_decrement =
+ base::Bind(&BrowserCompositorMac::CopyToVideoFrameCompleted,
+ weak_factory_.GetWeakPtr(), callback);
+
+ delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
+ src_subrect, target, callback_with_decrement);
+}
+
+void BrowserCompositorMac::SwapCompositorFrame(uint32_t output_surface_id,
+ cc::CompositorFrame frame) {
+ DCHECK(!has_been_destroyed_);
+
+ // Compute the frame size based on the root render pass rect size.
+ cc::RenderPass* root_pass =
+ frame.delegated_frame_data->render_pass_list.back().get();
+ float scale_factor = frame.metadata.device_scale_factor;
+ gfx::Size pixel_size = root_pass->output_rect.size();
+ gfx::Size dip_size = gfx::ConvertSizeToDIP(scale_factor, pixel_size);
+ root_layer_->SetBounds(gfx::Rect(dip_size));
+ if (recyclable_compositor_) {
+ recyclable_compositor_->compositor()->SetScaleAndSize(scale_factor,
+ pixel_size);
+ }
+ delegated_frame_host_->SwapDelegatedFrame(output_surface_id,
+ std::move(frame));
+}
+
+void BrowserCompositorMac::SetHasTransparentBackground(bool transparent) {
+ DCHECK(!has_been_destroyed_);
+ has_transparent_background_ = transparent;
+ if (recyclable_compositor_) {
+ recyclable_compositor_->compositor()->SetHostHasTransparentBackground(
+ has_transparent_background_);
+ }
+}
+
+void BrowserCompositorMac::UpdateVSyncParameters(
+ const base::TimeTicks& timebase,
+ const base::TimeDelta& interval) {
+ DCHECK(!has_been_destroyed_);
+ if (recyclable_compositor_) {
+ recyclable_compositor_->compositor()
+ ->vsync_manager()
+ ->UpdateVSyncParameters(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() {
+ if (has_been_destroyed_) {
+ DCHECK(state_ == HasNoCompositor);
+ return;
+ }
+
+ if (!render_widget_host_is_hidden_ || outstanding_copy_count_ > 0)
+ TransitionToState(HasAttachedCompositor);
+ else if (ns_view_attached_to_window_)
+ TransitionToState(HasDetachedCompositor);
+ else
+ TransitionToState(HasNoCompositor);
+}
+
+void BrowserCompositorMac::TransitionToState(State new_state) {
+ // Transition HasNoCompositor -> HasDetachedCompositor.
+ if (state_ == HasNoCompositor && new_state != HasNoCompositor) {
+ recyclable_compositor_ = RecyclableCompositorMac::Create();
+ recyclable_compositor_->compositor()->SetRootLayer(root_layer_.get());
+ recyclable_compositor_->compositor()->SetHostHasTransparentBackground(
+ has_transparent_background_);
+ recyclable_compositor_->accelerated_widget_mac()->SetNSView(
+ accelerated_widget_mac_ns_view_);
+ state_ = HasDetachedCompositor;
+ }
+
+ // Transition HasDetachedCompositor -> HasAttachedCompositor.
+ if (state_ == HasDetachedCompositor && new_state == HasAttachedCompositor) {
+ NSView* ns_view =
+ accelerated_widget_mac_ns_view_->AcceleratedWidgetGetNSView();
+ float scale_factor = ui::GetScaleFactorForNativeView(ns_view);
+ NSSize dip_ns_size = [ns_view bounds].size;
+ gfx::Size pixel_size(dip_ns_size.width * scale_factor,
+ dip_ns_size.height * scale_factor);
+
+ delegated_frame_host_->SetCompositor(recyclable_compositor_->compositor());
+ delegated_frame_host_->WasShown(ui::LatencyInfo());
+ // Unsuspend the browser compositor after showing the delegated frame host.
+ // If there is not a saved delegated frame, then the delegated frame host
+ // will keep the compositor locked until a delegated frame is swapped.
+ recyclable_compositor_->compositor()->SetScaleAndSize(scale_factor,
+ pixel_size);
+ 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 == HasNoCompositor) {
+ recyclable_compositor_->accelerated_widget_mac()->ResetNSView();
+ recyclable_compositor_->compositor()->SetScaleAndSize(1.0, gfx::Size(0, 0));
+ recyclable_compositor_->compositor()->SetRootLayer(nullptr);
+ RecyclableCompositorMac::Recycle(std::move(recyclable_compositor_));
+ state_ = HasNoCompositor;
+ }
+}
+
+// static
+void BrowserCompositorMac::DisableRecyclingForShutdown() {
+ g_has_shut_down = true;
+ g_spare_recyclable_compositor.Get().reset();
}
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698