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/delegated_frame_host.h" | 5 #include "content/browser/renderer_host/delegated_frame_host.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 | 44 |
45 DelegatedFrameHost::DelegatedFrameHost(const cc::FrameSinkId& frame_sink_id, | 45 DelegatedFrameHost::DelegatedFrameHost(const cc::FrameSinkId& frame_sink_id, |
46 DelegatedFrameHostClient* client) | 46 DelegatedFrameHostClient* client) |
47 : frame_sink_id_(frame_sink_id), | 47 : frame_sink_id_(frame_sink_id), |
48 client_(client), | 48 client_(client), |
49 compositor_(nullptr), | 49 compositor_(nullptr), |
50 tick_clock_(new base::DefaultTickClock()), | 50 tick_clock_(new base::DefaultTickClock()), |
51 skipped_frames_(false), | 51 skipped_frames_(false), |
52 background_color_(SK_ColorRED), | 52 background_color_(SK_ColorRED), |
53 current_scale_factor_(1.f), | 53 current_scale_factor_(1.f), |
54 can_lock_compositor_(YES_CAN_LOCK), | |
55 delegated_frame_evictor_(new DelegatedFrameEvictor(this)) { | 54 delegated_frame_evictor_(new DelegatedFrameEvictor(this)) { |
56 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); | 55 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); |
57 factory->GetContextFactory()->AddObserver(this); | 56 factory->GetContextFactory()->AddObserver(this); |
58 factory->GetContextFactoryPrivate()->GetSurfaceManager()->RegisterFrameSinkId( | 57 factory->GetContextFactoryPrivate()->GetSurfaceManager()->RegisterFrameSinkId( |
59 frame_sink_id_); | 58 frame_sink_id_); |
60 CreateCompositorFrameSinkSupport(); | 59 CreateCompositorFrameSinkSupport(); |
61 } | 60 } |
62 | 61 |
63 void DelegatedFrameHost::WasShown(const ui::LatencyInfo& latency_info) { | 62 void DelegatedFrameHost::WasShown(const ui::LatencyInfo& latency_info) { |
64 delegated_frame_evictor_->SetVisible(true); | 63 delegated_frame_evictor_->SetVisible(true); |
(...skipping 11 matching lines...) Expand all Loading... |
76 bool DelegatedFrameHost::HasSavedFrame() { | 75 bool DelegatedFrameHost::HasSavedFrame() { |
77 return delegated_frame_evictor_->HasFrame(); | 76 return delegated_frame_evictor_->HasFrame(); |
78 } | 77 } |
79 | 78 |
80 void DelegatedFrameHost::WasHidden() { | 79 void DelegatedFrameHost::WasHidden() { |
81 delegated_frame_evictor_->SetVisible(false); | 80 delegated_frame_evictor_->SetVisible(false); |
82 released_front_lock_ = NULL; | 81 released_front_lock_ = NULL; |
83 } | 82 } |
84 | 83 |
85 void DelegatedFrameHost::MaybeCreateResizeLock() { | 84 void DelegatedFrameHost::MaybeCreateResizeLock() { |
86 if (!ShouldCreateResizeLock()) | 85 DCHECK(!resize_lock_); |
| 86 |
| 87 if (!compositor_) |
87 return; | 88 return; |
88 DCHECK(compositor_); | |
89 | 89 |
90 bool defer_compositor_lock = | 90 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
91 can_lock_compositor_ == NO_PENDING_RENDERER_FRAME || | 91 switches::kDisableResizeLock)) |
92 can_lock_compositor_ == NO_PENDING_COMMIT; | 92 return; |
93 | 93 |
94 if (can_lock_compositor_ == YES_CAN_LOCK) | 94 if (!client_->DelegatedFrameCanCreateResizeLock()) |
95 can_lock_compositor_ = YES_DID_LOCK; | 95 return; |
| 96 |
| 97 gfx::Size desired_size = client_->DelegatedFrameHostDesiredSizeInDIP(); |
| 98 if (desired_size.IsEmpty()) |
| 99 return; |
| 100 if (desired_size == current_frame_size_in_dip_) |
| 101 return; |
96 | 102 |
97 resize_lock_ = client_->DelegatedFrameHostCreateResizeLock(); | 103 resize_lock_ = client_->DelegatedFrameHostCreateResizeLock(); |
98 if (!defer_compositor_lock) { | 104 bool locked = resize_lock_->Lock(); |
99 bool locked = resize_lock_->Lock(); | 105 DCHECK(locked); |
100 DCHECK(locked); | |
101 } | |
102 } | |
103 | |
104 bool DelegatedFrameHost::ShouldCreateResizeLock() { | |
105 static const bool is_disabled = | |
106 base::CommandLine::ForCurrentProcess()->HasSwitch( | |
107 switches::kDisableResizeLock); | |
108 if (is_disabled) | |
109 return false; | |
110 | |
111 if (!client_->DelegatedFrameCanCreateResizeLock()) | |
112 return false; | |
113 | |
114 if (resize_lock_) | |
115 return false; | |
116 | |
117 gfx::Size desired_size = client_->DelegatedFrameHostDesiredSizeInDIP(); | |
118 if (desired_size == current_frame_size_in_dip_ || desired_size.IsEmpty()) | |
119 return false; | |
120 | |
121 if (!compositor_) | |
122 return false; | |
123 | |
124 return true; | |
125 } | 106 } |
126 | 107 |
127 void DelegatedFrameHost::CopyFromCompositingSurface( | 108 void DelegatedFrameHost::CopyFromCompositingSurface( |
128 const gfx::Rect& src_subrect, | 109 const gfx::Rect& src_subrect, |
129 const gfx::Size& output_size, | 110 const gfx::Size& output_size, |
130 const ReadbackRequestCallback& callback, | 111 const ReadbackRequestCallback& callback, |
131 const SkColorType preferred_color_type) { | 112 const SkColorType preferred_color_type) { |
132 // Only ARGB888 and RGB565 supported as of now. | 113 // Only ARGB888 and RGB565 supported as of now. |
133 bool format_support = ((preferred_color_type == kAlpha_8_SkColorType) || | 114 bool format_support = ((preferred_color_type == kAlpha_8_SkColorType) || |
134 (preferred_color_type == kRGB_565_SkColorType) || | 115 (preferred_color_type == kRGB_565_SkColorType) || |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 // CompositorFrame's damage, so need to wait for the next one before | 226 // CompositorFrame's damage, so need to wait for the next one before |
246 // confirming newer sequence numbers. | 227 // confirming newer sequence numbers. |
247 modified_ack.has_damage = false; | 228 modified_ack.has_damage = false; |
248 modified_ack.latest_confirmed_sequence_number = | 229 modified_ack.latest_confirmed_sequence_number = |
249 latest_confirmed_begin_frame_sequence_number_; | 230 latest_confirmed_begin_frame_sequence_number_; |
250 } | 231 } |
251 | 232 |
252 support_->BeginFrameDidNotSwap(modified_ack); | 233 support_->BeginFrameDidNotSwap(modified_ack); |
253 } | 234 } |
254 | 235 |
255 bool DelegatedFrameHost::ShouldSkipFrame(gfx::Size size_in_dip) const { | 236 bool DelegatedFrameHost::ShouldSkipFrame(const gfx::Size& size_in_dip) { |
256 // Should skip a frame only when another frame from the renderer is guaranteed | 237 if (!resize_lock_) |
257 // to replace it. Otherwise may cause hangs when the renderer is waiting for | |
258 // the completion of latency infos (such as when taking a Snapshot.) | |
259 if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME || | |
260 can_lock_compositor_ == NO_PENDING_COMMIT || !resize_lock_.get()) | |
261 return false; | 238 return false; |
262 | 239 // Allow a single renderer frame through even though there's a resize lock |
| 240 // currently in place. |
| 241 if (allow_one_renderer_frame_during_resize_lock_) { |
| 242 allow_one_renderer_frame_during_resize_lock_ = false; |
| 243 return false; |
| 244 } |
263 return size_in_dip != resize_lock_->expected_size(); | 245 return size_in_dip != resize_lock_->expected_size(); |
264 } | 246 } |
265 | 247 |
266 void DelegatedFrameHost::WasResized() { | 248 void DelegatedFrameHost::WasResized() { |
267 if (client_->DelegatedFrameHostDesiredSizeInDIP() != | 249 if (client_->DelegatedFrameHostDesiredSizeInDIP() != |
268 current_frame_size_in_dip_ && | 250 current_frame_size_in_dip_ && |
269 !client_->DelegatedFrameHostIsVisible()) | 251 !client_->DelegatedFrameHostIsVisible()) |
270 EvictDelegatedFrame(); | 252 EvictDelegatedFrame(); |
271 MaybeCreateResizeLock(); | 253 // If |create_resize_lock_after_commit_| is true, we're waiting to recreate |
| 254 // an expired resize lock after the next UI frame is submitted, so don't |
| 255 // make a lock here. |
| 256 if (!resize_lock_ && !create_resize_lock_after_commit_) |
| 257 MaybeCreateResizeLock(); |
272 UpdateGutters(); | 258 UpdateGutters(); |
273 } | 259 } |
274 | 260 |
275 SkColor DelegatedFrameHost::GetGutterColor() const { | 261 SkColor DelegatedFrameHost::GetGutterColor() const { |
276 // In fullscreen mode resizing is uncommon, so it makes more sense to | 262 // In fullscreen mode resizing is uncommon, so it makes more sense to |
277 // make the initial switch to fullscreen mode look better by using black as | 263 // make the initial switch to fullscreen mode look better by using black as |
278 // the gutter color. | 264 // the gutter color. |
279 return client_->DelegatedFrameHostGetGutterColor(background_color_); | 265 return client_->DelegatedFrameHostGetGutterColor(background_color_); |
280 } | 266 } |
281 | 267 |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 frame.metadata.latency_info.begin(), | 414 frame.metadata.latency_info.begin(), |
429 frame.metadata.latency_info.end()); | 415 frame.metadata.latency_info.end()); |
430 | 416 |
431 client_->DelegatedFrameHostSendReclaimCompositorResources( | 417 client_->DelegatedFrameHostSendReclaimCompositorResources( |
432 true /* is_swap_ack*/, resources); | 418 true /* is_swap_ack*/, resources); |
433 skipped_frames_ = true; | 419 skipped_frames_ = true; |
434 BeginFrameDidNotSwap(ack); | 420 BeginFrameDidNotSwap(ack); |
435 return; | 421 return; |
436 } | 422 } |
437 | 423 |
| 424 // If we are allowing one renderer frame through, this would ensure the frame |
| 425 // gets through even if we regrab the lock after the UI compositor makes one |
| 426 // frame. If the renderer frame beats the UI compositor, then we don't need to |
| 427 // allow any more, though. |
| 428 allow_one_renderer_frame_during_resize_lock_ = false; |
| 429 |
438 if (skipped_frames_) { | 430 if (skipped_frames_) { |
439 skipped_frames_ = false; | 431 skipped_frames_ = false; |
440 damage_rect = gfx::Rect(frame_size); | 432 damage_rect = gfx::Rect(frame_size); |
441 damage_rect_in_dip = gfx::Rect(frame_size_in_dip); | 433 damage_rect_in_dip = gfx::Rect(frame_size_in_dip); |
442 | 434 |
443 // Give the same damage rect to the compositor. | 435 // Give the same damage rect to the compositor. |
444 cc::RenderPass* root_pass = frame.render_pass_list.back().get(); | 436 cc::RenderPass* root_pass = frame.render_pass_list.back().get(); |
445 root_pass->damage_rect = damage_rect; | 437 root_pass->damage_rect = damage_rect; |
446 } | 438 } |
447 | 439 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 current_frame_size_in_dip_ = frame_size_in_dip; | 473 current_frame_size_in_dip_ = frame_size_in_dip; |
482 CheckResizeLock(); | 474 CheckResizeLock(); |
483 | 475 |
484 UpdateGutters(); | 476 UpdateGutters(); |
485 | 477 |
486 if (!damage_rect_in_dip.IsEmpty()) { | 478 if (!damage_rect_in_dip.IsEmpty()) { |
487 client_->DelegatedFrameHostGetLayer()->OnDelegatedFrameDamage( | 479 client_->DelegatedFrameHostGetLayer()->OnDelegatedFrameDamage( |
488 damage_rect_in_dip); | 480 damage_rect_in_dip); |
489 } | 481 } |
490 | 482 |
491 if (compositor_) | |
492 can_lock_compositor_ = NO_PENDING_COMMIT; | |
493 | |
494 if (has_frame_) { | 483 if (has_frame_) { |
495 delegated_frame_evictor_->SwappedFrame( | 484 delegated_frame_evictor_->SwappedFrame( |
496 client_->DelegatedFrameHostIsVisible()); | 485 client_->DelegatedFrameHostIsVisible()); |
497 } | 486 } |
498 // Note: the frame may have been evicted immediately. | 487 // Note: the frame may have been evicted immediately. |
499 | 488 |
500 DidFinishFrame(ack); | 489 DidFinishFrame(ack); |
501 } | 490 } |
502 | 491 |
503 void DelegatedFrameHost::ClearDelegatedFrame() { | 492 void DelegatedFrameHost::ClearDelegatedFrame() { |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
703 video_frame->stride(media::VideoFrame::kVPlane), | 692 video_frame->stride(media::VideoFrame::kVPlane), |
704 video_frame->data(media::VideoFrame::kVPlane), region_in_frame.origin(), | 693 video_frame->data(media::VideoFrame::kVPlane), region_in_frame.origin(), |
705 finished_callback); | 694 finished_callback); |
706 media::LetterboxYUV(video_frame.get(), region_in_frame); | 695 media::LetterboxYUV(video_frame.get(), region_in_frame); |
707 } | 696 } |
708 | 697 |
709 //////////////////////////////////////////////////////////////////////////////// | 698 //////////////////////////////////////////////////////////////////////////////// |
710 // DelegatedFrameHost, ui::CompositorObserver implementation: | 699 // DelegatedFrameHost, ui::CompositorObserver implementation: |
711 | 700 |
712 void DelegatedFrameHost::OnCompositingDidCommit(ui::Compositor* compositor) { | 701 void DelegatedFrameHost::OnCompositingDidCommit(ui::Compositor* compositor) { |
713 if (can_lock_compositor_ == NO_PENDING_COMMIT) { | 702 // If |create_resize_lock_after_commit_| then we should have popped the old |
714 can_lock_compositor_ = YES_CAN_LOCK; | 703 // lock already. |
715 if (resize_lock_ && resize_lock_->Lock()) | 704 DCHECK(!resize_lock_ || !create_resize_lock_after_commit_); |
716 can_lock_compositor_ = YES_DID_LOCK; | 705 |
717 } | |
718 if (resize_lock_ && | 706 if (resize_lock_ && |
719 resize_lock_->expected_size() == current_frame_size_in_dip_) { | 707 resize_lock_->expected_size() == current_frame_size_in_dip_) { |
720 resize_lock_.reset(); | 708 resize_lock_.reset(); |
721 client_->DelegatedFrameHostResizeLockWasReleased(); | 709 // We had a lock but the UI may have resized in the meantime. |
722 // We may have had a resize while we had the lock (e.g. if the lock expired, | 710 create_resize_lock_after_commit_ = true; |
723 // or if the UI still gave us some resizes), so make sure we grab a new lock | 711 } |
724 // if necessary. | 712 |
| 713 if (create_resize_lock_after_commit_) { |
| 714 create_resize_lock_after_commit_ = false; |
725 MaybeCreateResizeLock(); | 715 MaybeCreateResizeLock(); |
726 } | 716 } |
727 } | 717 } |
728 | 718 |
729 void DelegatedFrameHost::OnCompositingStarted(ui::Compositor* compositor, | 719 void DelegatedFrameHost::OnCompositingStarted(ui::Compositor* compositor, |
730 base::TimeTicks start_time) { | 720 base::TimeTicks start_time) { |
731 last_draw_ended_ = start_time; | 721 last_draw_ended_ = start_time; |
732 } | 722 } |
733 | 723 |
734 void DelegatedFrameHost::OnCompositingLockStateChanged( | 724 void DelegatedFrameHost::OnCompositingLockStateChanged( |
735 ui::Compositor* compositor) { | 725 ui::Compositor* compositor) { |
736 // A compositor lock that is part of a resize lock timed out. We | 726 if (resize_lock_ && resize_lock_->timed_out()) { |
737 // should display a renderer frame. | 727 // A compositor lock that is part of a resize lock timed out. We allow |
738 if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) { | 728 // the UI to produce a frame before locking it again, so we don't lock here. |
739 can_lock_compositor_ = NO_PENDING_RENDERER_FRAME; | 729 // We release the |resize_lock_| though to allow any other resizes that are |
| 730 // desired at the same time since we're allowing the UI to make a frame |
| 731 // which will gutter anyways. |
| 732 resize_lock_.reset(); |
| 733 create_resize_lock_after_commit_ = true; |
| 734 // Because this timed out, we're going to allow the UI to update and lock |
| 735 // again. We would allow renderer frames through during this time if they |
| 736 // came late, but would stop them again once the UI finished its frame. We |
| 737 // want to allow the slow renderer to show us one frame even if its wrong |
| 738 // since we're guttering anyways, but not unlimited number of frames as that |
| 739 // would be a waste of power. |
| 740 allow_one_renderer_frame_during_resize_lock_ = true; |
740 } | 741 } |
741 } | 742 } |
742 | 743 |
743 void DelegatedFrameHost::OnCompositingShuttingDown(ui::Compositor* compositor) { | 744 void DelegatedFrameHost::OnCompositingShuttingDown(ui::Compositor* compositor) { |
744 DCHECK_EQ(compositor, compositor_); | 745 DCHECK_EQ(compositor, compositor_); |
745 ResetCompositor(); | 746 ResetCompositor(); |
746 DCHECK(!compositor_); | 747 DCHECK(!compositor_); |
747 } | 748 } |
748 | 749 |
749 void DelegatedFrameHost::OnUpdateVSyncParameters(base::TimeTicks timebase, | 750 void DelegatedFrameHost::OnUpdateVSyncParameters(base::TimeTicks timebase, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 DCHECK(!vsync_manager_.get()); | 788 DCHECK(!vsync_manager_.get()); |
788 vsync_manager_ = compositor_->vsync_manager(); | 789 vsync_manager_ = compositor_->vsync_manager(); |
789 vsync_manager_->AddObserver(this); | 790 vsync_manager_->AddObserver(this); |
790 | 791 |
791 compositor_->AddFrameSink(frame_sink_id_); | 792 compositor_->AddFrameSink(frame_sink_id_); |
792 } | 793 } |
793 | 794 |
794 void DelegatedFrameHost::ResetCompositor() { | 795 void DelegatedFrameHost::ResetCompositor() { |
795 if (!compositor_) | 796 if (!compositor_) |
796 return; | 797 return; |
797 if (resize_lock_) { | 798 resize_lock_.reset(); |
798 resize_lock_.reset(); | |
799 client_->DelegatedFrameHostResizeLockWasReleased(); | |
800 } | |
801 if (compositor_->HasObserver(this)) | 799 if (compositor_->HasObserver(this)) |
802 compositor_->RemoveObserver(this); | 800 compositor_->RemoveObserver(this); |
803 if (vsync_manager_) { | 801 if (vsync_manager_) { |
804 vsync_manager_->RemoveObserver(this); | 802 vsync_manager_->RemoveObserver(this); |
805 vsync_manager_ = nullptr; | 803 vsync_manager_ = nullptr; |
806 } | 804 } |
807 | 805 |
808 compositor_->RemoveFrameSink(frame_sink_id_); | 806 compositor_->RemoveFrameSink(frame_sink_id_); |
809 compositor_ = nullptr; | 807 compositor_ = nullptr; |
810 } | 808 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
864 } | 862 } |
865 | 863 |
866 if (!skipped_frames_) { | 864 if (!skipped_frames_) { |
867 latest_confirmed_begin_frame_source_id_ = ack.source_id; | 865 latest_confirmed_begin_frame_source_id_ = ack.source_id; |
868 latest_confirmed_begin_frame_sequence_number_ = | 866 latest_confirmed_begin_frame_sequence_number_ = |
869 ack.latest_confirmed_sequence_number; | 867 ack.latest_confirmed_sequence_number; |
870 } | 868 } |
871 } | 869 } |
872 | 870 |
873 } // namespace content | 871 } // namespace content |
OLD | NEW |