Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 |
| OLD | NEW |