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

Side by Side 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: Clean up destroy, rebase Created 4 years, 5 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/browser_compositor_view_mac.h" 5 #include "content/browser/renderer_host/browser_compositor_view_mac.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/trace_event/trace_event.h" 12 #include "base/trace_event/trace_event.h"
13 #include "content/browser/compositor/image_transport_factory.h" 13 #include "content/browser/compositor/image_transport_factory.h"
14 #include "content/public/browser/context_factory.h" 14 #include "content/public/browser/context_factory.h"
15 #include "ui/accelerated_widget_mac/accelerated_widget_mac.h" 15 #include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
16 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" 16 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
17 17 #include "ui/base/layout.h"
18 //////////////////////////////////////////////////////////////////////////////// 18 #include "ui/gfx/geometry/dip_util.h"
19 // BrowserCompositorMac
20 19
21 namespace content { 20 namespace content {
22 21
23 namespace { 22 namespace {
24 23
25 // Set when no browser compositors should remain alive. 24 // Set when no browser compositors should remain alive.
26 bool g_has_shut_down = false; 25 bool g_has_shut_down = false;
27 26
28 // The number of placeholder objects allocated. If this reaches zero, then 27 // The number of placeholder objects allocated. If this reaches zero, then
29 // the BrowserCompositorMac being held on to for recycling, 28 // the RecyclableCompositorMac being held on to for recycling,
30 // |g_recyclable_browser_compositor|, will be freed. 29 // |g_spare_recyclable_compositor|, will be freed.
31 uint32_t g_placeholder_count = 0; 30 uint32_t g_browser_compositor_count = 0;
32 31
33 // A spare BrowserCompositorMac kept around for recycling. 32 // A spare RecyclableCompositorMac kept around for recycling.
34 base::LazyInstance<std::unique_ptr<BrowserCompositorMac>> 33 base::LazyInstance<std::unique_ptr<RecyclableCompositorMac>>
35 g_recyclable_browser_compositor; 34 g_spare_recyclable_compositor;
36 35
37 } // namespace 36 } // namespace
38 37
39 BrowserCompositorMac::BrowserCompositorMac() 38 ////////////////////////////////////////////////////////////////////////////////
39 // RecyclableCompositorMac
40
41 // A ui::Compositor and a gfx::AcceleratedWidget (and helper) that it draws
42 // into. This structure is used to efficiently recycle these structures across
43 // tabs (because creating a new ui::Compositor for each tab would be expensive
44 // in terms of time and resources).
45 class RecyclableCompositorMac : public ui::CompositorObserver {
46 public:
47 virtual ~RecyclableCompositorMac();
48
49 // Create a compositor, or recycle a preexisting one.
50 static std::unique_ptr<RecyclableCompositorMac> Create();
51
52 // Delete a compositor, or allow it to be recycled.
53 static void Recycle(std::unique_ptr<RecyclableCompositorMac> compositor);
54
55 // Indicate that the recyclable compositor should be destroyed, and no future
56 // compositors should be recycled.
57 static void DisableRecyclingForShutdown();
58
59 ui::Compositor* compositor() { return &compositor_; }
60 ui::AcceleratedWidgetMac* accelerated_widget_mac() {
61 return accelerated_widget_mac_.get();
62 }
63
64 // Suspend will prevent the compositor from producing new frames. This should
65 // be called to avoid creating spurious frames while changing state.
66 // Compositors are created as suspended.
67 void Suspend();
68 void Unsuspend();
69
70 private:
71 RecyclableCompositorMac();
72
73 // ui::CompositorObserver implementation:
74 void OnCompositingDidCommit(ui::Compositor* compositor) override;
75 void OnCompositingStarted(ui::Compositor* compositor,
76 base::TimeTicks start_time) override {}
77 void OnCompositingEnded(ui::Compositor* compositor) override {}
78 void OnCompositingAborted(ui::Compositor* compositor) override {}
79 void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
80 void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
81
82 std::unique_ptr<ui::AcceleratedWidgetMac> accelerated_widget_mac_;
83 ui::Compositor compositor_;
84 scoped_refptr<ui::CompositorLock> compositor_suspended_lock_;
85
86 DISALLOW_COPY_AND_ASSIGN(RecyclableCompositorMac);
87 };
88
89 RecyclableCompositorMac::RecyclableCompositorMac()
40 : accelerated_widget_mac_(new ui::AcceleratedWidgetMac()), 90 : accelerated_widget_mac_(new ui::AcceleratedWidgetMac()),
41 compositor_(content::GetContextFactory(), 91 compositor_(content::GetContextFactory(),
42 ui::WindowResizeHelperMac::Get()->task_runner()) { 92 ui::WindowResizeHelperMac::Get()->task_runner()) {
43 compositor_.SetAcceleratedWidget( 93 compositor_.SetAcceleratedWidget(
44 accelerated_widget_mac_->accelerated_widget()); 94 accelerated_widget_mac_->accelerated_widget());
45 compositor_.SetLocksWillTimeOut(false); 95 compositor_.SetLocksWillTimeOut(false);
46 Suspend(); 96 Suspend();
47 compositor_.AddObserver(this); 97 compositor_.AddObserver(this);
48 } 98 }
49 99
50 BrowserCompositorMac::~BrowserCompositorMac() { 100 RecyclableCompositorMac::~RecyclableCompositorMac() {
51 compositor_.RemoveObserver(this); 101 compositor_.RemoveObserver(this);
52 } 102 }
53 103
54 void BrowserCompositorMac::Suspend() { 104 void RecyclableCompositorMac::Suspend() {
55 compositor_suspended_lock_ = compositor_.GetCompositorLock(); 105 compositor_suspended_lock_ = compositor_.GetCompositorLock();
56 } 106 }
57 107
58 void BrowserCompositorMac::Unsuspend() { 108 void RecyclableCompositorMac::Unsuspend() {
59 compositor_suspended_lock_ = nullptr; 109 compositor_suspended_lock_ = nullptr;
60 } 110 }
61 111
62 void BrowserCompositorMac::OnCompositingDidCommit( 112 void RecyclableCompositorMac::OnCompositingDidCommit(
63 ui::Compositor* compositor_that_did_commit) { 113 ui::Compositor* compositor_that_did_commit) {
64 DCHECK_EQ(compositor_that_did_commit, compositor()); 114 DCHECK_EQ(compositor_that_did_commit, compositor());
65 content::ImageTransportFactory::GetInstance() 115 content::ImageTransportFactory::GetInstance()
66 ->SetCompositorSuspendedForRecycle(compositor(), false); 116 ->SetCompositorSuspendedForRecycle(compositor(), false);
67 } 117 }
68 118
69 // static 119 // static
70 std::unique_ptr<BrowserCompositorMac> BrowserCompositorMac::Create() { 120 std::unique_ptr<RecyclableCompositorMac> RecyclableCompositorMac::Create() {
71 DCHECK(ui::WindowResizeHelperMac::Get()->task_runner()); 121 DCHECK(ui::WindowResizeHelperMac::Get()->task_runner());
72 if (g_recyclable_browser_compositor.Get()) 122 if (g_spare_recyclable_compositor.Get())
73 return std::move(g_recyclable_browser_compositor.Get()); 123 return std::move(g_spare_recyclable_compositor.Get());
74 return std::unique_ptr<BrowserCompositorMac>(new BrowserCompositorMac); 124 return std::unique_ptr<RecyclableCompositorMac>(new RecyclableCompositorMac);
75 } 125 }
76 126
77 // static 127 // static
78 void BrowserCompositorMac::Recycle( 128 void RecyclableCompositorMac::Recycle(
79 std::unique_ptr<BrowserCompositorMac> compositor) { 129 std::unique_ptr<RecyclableCompositorMac> compositor) {
80 DCHECK(compositor); 130 DCHECK(compositor);
81 content::ImageTransportFactory::GetInstance() 131 content::ImageTransportFactory::GetInstance()
82 ->SetCompositorSuspendedForRecycle(compositor->compositor(), true); 132 ->SetCompositorSuspendedForRecycle(compositor->compositor(), true);
83 133
84 // It is an error to have a browser compositor continue to exist after 134 // It is an error to have a browser compositor continue to exist after
85 // shutdown. 135 // shutdown.
86 CHECK(!g_has_shut_down); 136 CHECK(!g_has_shut_down);
87 137
88 // Make this BrowserCompositorMac recyclable for future instances. 138 // Make this RecyclableCompositorMac recyclable for future instances.
89 g_recyclable_browser_compositor.Get().swap(compositor); 139 g_spare_recyclable_compositor.Get().swap(compositor);
90 140
91 // If there are no placeholders allocated, destroy the recyclable 141 // If there are no placeholders allocated, destroy the recyclable
92 // BrowserCompositorMac that we just populated. 142 // RecyclableCompositorMac that we just populated.
93 if (!g_placeholder_count) 143 if (!g_browser_compositor_count)
94 g_recyclable_browser_compositor.Get().reset(); 144 g_spare_recyclable_compositor.Get().reset();
145 }
146
147 ////////////////////////////////////////////////////////////////////////////////
148 // BrowserCompositorMac
149
150 BrowserCompositorMac::BrowserCompositorMac(
151 ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view,
152 DelegatedFrameHostClient* delegated_frame_host_client,
153 bool render_widget_host_is_hidden,
154 bool ns_view_attached_to_window)
155 : accelerated_widget_mac_ns_view_(accelerated_widget_mac_ns_view),
156 weak_factory_(this) {
157 g_browser_compositor_count += 1;
158
159 root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
160 delegated_frame_host_.reset(
161 new DelegatedFrameHost(delegated_frame_host_client));
162
163 SetRenderWidgetHostIsHidden(render_widget_host_is_hidden);
164 SetNSViewAttachedToWindow(ns_view_attached_to_window);
165 }
166
167 BrowserCompositorMac::~BrowserCompositorMac() {
168 DCHECK(has_been_destroyed_);
169 }
170
171 void BrowserCompositorMac::Destroy() {
172 if (has_been_destroyed_)
173 return;
174
175 TransitionToState(HasNoCompositor);
176 delegated_frame_host_.reset();
177 root_layer_.reset();
178 has_been_destroyed_ = true;
179
180 DCHECK_GT(g_browser_compositor_count, 0u);
181 g_browser_compositor_count -= 1;
182
183 // If there are no compositors allocated, destroy the recyclable
184 // RecyclableCompositorMac.
185 if (!g_browser_compositor_count)
186 g_spare_recyclable_compositor.Get().reset();
187 }
188
189 ui::AcceleratedWidgetMac* BrowserCompositorMac::GetAcceleratedWidgetMac() {
190 if (recyclable_compositor_)
191 return recyclable_compositor_->accelerated_widget_mac();
192 return nullptr;
193 }
194
195 ui::Layer* BrowserCompositorMac::GetRootLayer() {
196 return root_layer_.get();
197 }
198
199 DelegatedFrameHost* BrowserCompositorMac::GetDelegatedFrameHost() {
200 DCHECK(delegated_frame_host_);
201 return delegated_frame_host_.get();
202 }
203
204 void BrowserCompositorMac::CopyCompleted(
205 base::WeakPtr<BrowserCompositorMac> browser_compositor,
206 const ReadbackRequestCallback& callback,
207 const SkBitmap& bitmap,
208 ReadbackResponse response) {
209 callback.Run(bitmap, response);
210 if (browser_compositor) {
211 browser_compositor->outstanding_copy_count_ -= 1;
212 browser_compositor->UpdateState();
213 }
214 }
215
216 void BrowserCompositorMac::CopyFromCompositingSurface(
217 const gfx::Rect& src_subrect,
218 const gfx::Size& dst_size,
219 const ReadbackRequestCallback& callback,
220 SkColorType preferred_color_type) {
221 DCHECK(delegated_frame_host_);
222 DCHECK(state_ == HasAttachedCompositor);
223 outstanding_copy_count_ += 1;
224
225 auto callback_with_decrement =
226 base::Bind(&BrowserCompositorMac::CopyCompleted,
227 weak_factory_.GetWeakPtr(), callback);
228 delegated_frame_host_->CopyFromCompositingSurface(
229 src_subrect, dst_size, callback_with_decrement, preferred_color_type);
230 }
231
232 void BrowserCompositorMac::CopyToVideoFrameCompleted(
233 base::WeakPtr<BrowserCompositorMac> browser_compositor,
234 const base::Callback<void(const gfx::Rect&, bool)>& callback,
235 const gfx::Rect& rect,
236 bool result) {
237 callback.Run(rect, result);
238 if (browser_compositor) {
239 browser_compositor->outstanding_copy_count_ -= 1;
240 browser_compositor->UpdateState();
241 }
242 }
243
244 void BrowserCompositorMac::CopyFromCompositingSurfaceToVideoFrame(
245 const gfx::Rect& src_subrect,
246 const scoped_refptr<media::VideoFrame>& target,
247 const base::Callback<void(const gfx::Rect&, bool)>& callback) {
248 DCHECK(delegated_frame_host_);
249 DCHECK(state_ == HasAttachedCompositor);
250 outstanding_copy_count_ += 1;
251
252 auto callback_with_decrement =
253 base::Bind(&BrowserCompositorMac::CopyToVideoFrameCompleted,
254 weak_factory_.GetWeakPtr(), callback);
255
256 delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
257 src_subrect, target, callback_with_decrement);
258 }
259
260 void BrowserCompositorMac::SwapCompositorFrame(
261 uint32_t output_surface_id,
262 cc::CompositorFrame frame,
263 bool render_widget_host_is_hidden) {
264 DCHECK(!has_been_destroyed_);
265
266 // TODO(ccameron): This would not be needed if BrowserCompostiorMac were to
267 // correctly subscribe to the show and hide notifications for
268 // RenderWidgetHostImpl. We do not correctly subscribe to these notifications
269 // because we want to set the hide property property only after all
270 // notifications (the thumbnailer in particular) have all completed.
271 SetRenderWidgetHostIsHidden(render_widget_host_is_hidden);
enne (OOO) 2016/06/28 00:25:37 This is really being called just for UpdateState a
ccameron 2016/06/28 07:04:11 This is intended as a "oh no, somehow we didn't ge
ccameron 2016/06/28 17:49:39 Moved this "set" to the RWHVMac to be more clear t
272
273 float scale_factor = frame.metadata.device_scale_factor;
274
275 // Compute the frame size based on the root render pass rect size.
276 cc::RenderPass* root_pass =
277 frame.delegated_frame_data->render_pass_list.back().get();
278 gfx::Size pixel_size = root_pass->output_rect.size();
279 gfx::Size dip_size = gfx::ConvertSizeToDIP(scale_factor, pixel_size);
280 root_layer_->SetBounds(gfx::Rect(dip_size));
281 if (recyclable_compositor_) {
282 recyclable_compositor_->compositor()->SetScaleAndSize(scale_factor,
283 pixel_size);
284 }
285 delegated_frame_host_->SwapDelegatedFrame(output_surface_id,
286 std::move(frame));
287 }
288
289 void BrowserCompositorMac::SetHasTransparentBackground(bool transparent) {
290 DCHECK(!has_been_destroyed_);
291 has_transparent_background_ = transparent;
292 if (recyclable_compositor_) {
293 recyclable_compositor_->compositor()->SetHostHasTransparentBackground(
294 has_transparent_background_);
295 }
296 }
297
298 void BrowserCompositorMac::UpdateVSyncParameters(
299 const base::TimeTicks& timebase,
300 const base::TimeDelta& interval) {
301 DCHECK(!has_been_destroyed_);
302 if (recyclable_compositor_) {
303 recyclable_compositor_->compositor()
304 ->vsync_manager()
305 ->UpdateVSyncParameters(timebase, interval);
306 }
307 }
308
309 void BrowserCompositorMac::SetRenderWidgetHostIsHidden(bool hidden) {
310 render_widget_host_is_hidden_ = hidden;
311 UpdateState();
312 }
313
314 void BrowserCompositorMac::SetNSViewAttachedToWindow(bool attached) {
315 ns_view_attached_to_window_ = attached;
316 UpdateState();
317 }
318
319 void BrowserCompositorMac::UpdateState() {
320 if (has_been_destroyed_) {
321 DCHECK(state_ == HasNoCompositor);
322 return;
323 }
324
325 if (!render_widget_host_is_hidden_ || outstanding_copy_count_ > 0)
326 TransitionToState(HasAttachedCompositor);
327 else if (ns_view_attached_to_window_)
328 TransitionToState(HasDetachedCompositor);
329 else
330 TransitionToState(HasNoCompositor);
331 }
332
333 void BrowserCompositorMac::TransitionToState(State new_state) {
334 // Transition HasNoCompositor -> HasDetachedCompositor.
335 if (state_ == HasNoCompositor && new_state != HasNoCompositor) {
336 recyclable_compositor_ = RecyclableCompositorMac::Create();
337 recyclable_compositor_->compositor()->SetRootLayer(root_layer_.get());
338 recyclable_compositor_->compositor()->SetHostHasTransparentBackground(
339 has_transparent_background_);
340 recyclable_compositor_->accelerated_widget_mac()->SetNSView(
341 accelerated_widget_mac_ns_view_);
342 state_ = HasDetachedCompositor;
343 }
344
345 // Transition HasDetachedCompositor -> HasAttachedCompositor.
346 if (state_ == HasDetachedCompositor && new_state == HasAttachedCompositor) {
347 NSView* ns_view =
348 accelerated_widget_mac_ns_view_->AcceleratedWidgetGetNSView();
349 float scale_factor = ui::GetScaleFactorForNativeView(ns_view);
350 NSSize dip_ns_size = [ns_view bounds].size;
351 gfx::Size pixel_size(dip_ns_size.width * scale_factor,
352 dip_ns_size.height * scale_factor);
353
354 delegated_frame_host_->SetCompositor(recyclable_compositor_->compositor());
355 delegated_frame_host_->WasShown(ui::LatencyInfo());
356 // Unsuspend the browser compositor after showing the delegated frame host.
357 // If there is not a saved delegated frame, then the delegated frame host
358 // will keep the compositor locked until a delegated frame is swapped.
359 recyclable_compositor_->compositor()->SetScaleAndSize(scale_factor,
360 pixel_size);
361 recyclable_compositor_->Unsuspend();
362 state_ = HasAttachedCompositor;
363 }
364
365 // Transition HasAttachedCompositor -> HasDetachedCompositor.
366 if (state_ == HasAttachedCompositor && new_state != HasAttachedCompositor) {
367 // Ensure that any changes made to the ui::Compositor do not result in new
368 // frames being produced.
369 recyclable_compositor_->Suspend();
370 // Marking the DelegatedFrameHost as removed from the window hierarchy is
371 // necessary to remove all connections to its old ui::Compositor.
372 delegated_frame_host_->WasHidden();
373 delegated_frame_host_->ResetCompositor();
374 state_ = HasDetachedCompositor;
375 }
376
377 // Transition HasDetachedCompositor -> HasNoCompositor.
378 if (state_ == HasDetachedCompositor && new_state == HasNoCompositor) {
379 recyclable_compositor_->accelerated_widget_mac()->ResetNSView();
380 recyclable_compositor_->compositor()->SetScaleAndSize(1.0, gfx::Size(0, 0));
381 recyclable_compositor_->compositor()->SetRootLayer(nullptr);
382 RecyclableCompositorMac::Recycle(std::move(recyclable_compositor_));
383 state_ = HasNoCompositor;
384 }
95 } 385 }
96 386
97 // static 387 // static
98 void BrowserCompositorMac::DisableRecyclingForShutdown() { 388 void BrowserCompositorMac::DisableRecyclingForShutdown() {
99 g_has_shut_down = true; 389 g_has_shut_down = true;
100 g_recyclable_browser_compositor.Get().reset(); 390 g_spare_recyclable_compositor.Get().reset();
101 }
102
103 ////////////////////////////////////////////////////////////////////////////////
104 // BrowserCompositorMacPlaceholder
105
106 BrowserCompositorMacPlaceholder::BrowserCompositorMacPlaceholder() {
107 g_placeholder_count += 1;
108 }
109
110 BrowserCompositorMacPlaceholder::~BrowserCompositorMacPlaceholder() {
111 DCHECK_GT(g_placeholder_count, 0u);
112 g_placeholder_count -= 1;
113
114 // If there are no placeholders allocated, destroy the recyclable
115 // BrowserCompositorMac.
116 if (!g_placeholder_count)
117 g_recyclable_browser_compositor.Get().reset();
118 } 391 }
119 392
120 } // namespace content 393 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698