OLD | NEW |
1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 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 "cc/trees/thread_proxy.h" | 5 #include "cc/trees/thread_proxy.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/metrics/histogram.h" |
10 #include "cc/base/thread.h" | 11 #include "cc/base/thread.h" |
11 #include "cc/input/input_handler.h" | 12 #include "cc/input/input_handler.h" |
12 #include "cc/output/context_provider.h" | 13 #include "cc/output/context_provider.h" |
13 #include "cc/output/output_surface.h" | 14 #include "cc/output/output_surface.h" |
14 #include "cc/quads/draw_quad.h" | 15 #include "cc/quads/draw_quad.h" |
15 #include "cc/resources/prioritized_resource_manager.h" | 16 #include "cc/resources/prioritized_resource_manager.h" |
16 #include "cc/scheduler/delay_based_time_source.h" | 17 #include "cc/scheduler/delay_based_time_source.h" |
17 #include "cc/scheduler/frame_rate_controller.h" | 18 #include "cc/scheduler/frame_rate_controller.h" |
18 #include "cc/scheduler/scheduler.h" | 19 #include "cc/scheduler/scheduler.h" |
19 #include "cc/scheduler/vsync_time_source.h" | 20 #include "cc/scheduler/vsync_time_source.h" |
20 #include "cc/trees/layer_tree_host.h" | 21 #include "cc/trees/layer_tree_host.h" |
21 #include "cc/trees/layer_tree_impl.h" | 22 #include "cc/trees/layer_tree_impl.h" |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 // Measured in seconds. | 26 // Measured in seconds. |
26 const double kContextRecreationTickRate = 0.03; | 27 const double kContextRecreationTickRate = 0.03; |
27 | 28 |
28 // Measured in seconds. | 29 // Measured in seconds. |
29 const double kSmoothnessTakesPriorityExpirationDelay = 0.25; | 30 const double kSmoothnessTakesPriorityExpirationDelay = 0.25; |
30 | 31 |
| 32 const size_t kDrawDurationHistorySize = 60; |
| 33 const double kDrawDurationEstimationPercentile = 100.0; |
| 34 const int kDrawDurationEstimatePaddingInMicroseconds = 0; |
| 35 |
31 } // namespace | 36 } // namespace |
32 | 37 |
33 namespace cc { | 38 namespace cc { |
34 | 39 |
35 scoped_ptr<Proxy> ThreadProxy::Create(LayerTreeHost* layer_tree_host, | 40 scoped_ptr<Proxy> ThreadProxy::Create(LayerTreeHost* layer_tree_host, |
36 scoped_ptr<Thread> impl_thread) { | 41 scoped_ptr<Thread> impl_thread) { |
37 return make_scoped_ptr( | 42 return make_scoped_ptr( |
38 new ThreadProxy(layer_tree_host, impl_thread.Pass())).PassAs<Proxy>(); | 43 new ThreadProxy(layer_tree_host, impl_thread.Pass())).PassAs<Proxy>(); |
39 } | 44 } |
40 | 45 |
(...skipping 19 matching lines...) Expand all Loading... |
60 next_frame_is_newly_committed_frame_on_impl_thread_(false), | 65 next_frame_is_newly_committed_frame_on_impl_thread_(false), |
61 throttle_frame_production_( | 66 throttle_frame_production_( |
62 layer_tree_host->settings().throttle_frame_production), | 67 layer_tree_host->settings().throttle_frame_production), |
63 begin_frame_scheduling_enabled_( | 68 begin_frame_scheduling_enabled_( |
64 layer_tree_host->settings().begin_frame_scheduling_enabled), | 69 layer_tree_host->settings().begin_frame_scheduling_enabled), |
65 using_synchronous_renderer_compositor_( | 70 using_synchronous_renderer_compositor_( |
66 layer_tree_host->settings().using_synchronous_renderer_compositor), | 71 layer_tree_host->settings().using_synchronous_renderer_compositor), |
67 vsync_client_(NULL), | 72 vsync_client_(NULL), |
68 inside_draw_(false), | 73 inside_draw_(false), |
69 defer_commits_(false), | 74 defer_commits_(false), |
70 renew_tree_priority_on_impl_thread_pending_(false) { | 75 renew_tree_priority_on_impl_thread_pending_(false), |
| 76 draw_duration_history_(kDrawDurationHistorySize) { |
71 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy"); | 77 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy"); |
72 DCHECK(IsMainThread()); | 78 DCHECK(IsMainThread()); |
73 DCHECK(layer_tree_host_); | 79 DCHECK(layer_tree_host_); |
74 } | 80 } |
75 | 81 |
76 ThreadProxy::~ThreadProxy() { | 82 ThreadProxy::~ThreadProxy() { |
77 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy"); | 83 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy"); |
78 DCHECK(IsMainThread()); | 84 DCHECK(IsMainThread()); |
79 DCHECK(!started_); | 85 DCHECK(!started_); |
80 } | 86 } |
(...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 DCHECK(IsImplThread()); | 876 DCHECK(IsImplThread()); |
871 Proxy::MainThread()->PostTask( | 877 Proxy::MainThread()->PostTask( |
872 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface, | 878 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface, |
873 main_thread_weak_ptr_)); | 879 main_thread_weak_ptr_)); |
874 } | 880 } |
875 | 881 |
876 ScheduledActionDrawAndSwapResult | 882 ScheduledActionDrawAndSwapResult |
877 ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) { | 883 ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) { |
878 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap"); | 884 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap"); |
879 | 885 |
| 886 base::TimeTicks start_time = base::TimeTicks::HighResNow(); |
| 887 base::TimeDelta draw_duration_estimate = DrawDurationEstimate(); |
880 base::AutoReset<bool> mark_inside(&inside_draw_, true); | 888 base::AutoReset<bool> mark_inside(&inside_draw_, true); |
881 | 889 |
882 ScheduledActionDrawAndSwapResult result; | 890 ScheduledActionDrawAndSwapResult result; |
883 result.did_draw = false; | 891 result.did_draw = false; |
884 result.did_swap = false; | 892 result.did_swap = false; |
885 DCHECK(IsImplThread()); | 893 DCHECK(IsImplThread()); |
886 DCHECK(layer_tree_host_impl_.get()); | 894 DCHECK(layer_tree_host_impl_.get()); |
887 if (!layer_tree_host_impl_) | 895 if (!layer_tree_host_impl_) |
888 return result; | 896 return result; |
889 | 897 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
961 DidSwapUseIncompleteTileOnImplThread(); | 969 DidSwapUseIncompleteTileOnImplThread(); |
962 } | 970 } |
963 | 971 |
964 // Tell the main thread that the the newly-commited frame was drawn. | 972 // Tell the main thread that the the newly-commited frame was drawn. |
965 if (next_frame_is_newly_committed_frame_on_impl_thread_) { | 973 if (next_frame_is_newly_committed_frame_on_impl_thread_) { |
966 next_frame_is_newly_committed_frame_on_impl_thread_ = false; | 974 next_frame_is_newly_committed_frame_on_impl_thread_ = false; |
967 Proxy::MainThread()->PostTask( | 975 Proxy::MainThread()->PostTask( |
968 base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_)); | 976 base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_)); |
969 } | 977 } |
970 | 978 |
971 if (draw_frame) | 979 if (draw_frame) { |
972 CheckOutputSurfaceStatusOnImplThread(); | 980 CheckOutputSurfaceStatusOnImplThread(); |
973 | 981 |
| 982 base::TimeDelta draw_duration = base::TimeTicks::HighResNow() - start_time; |
| 983 draw_duration_history_.InsertSample(draw_duration); |
| 984 base::TimeDelta draw_duration_overestimate; |
| 985 base::TimeDelta draw_duration_underestimate; |
| 986 if (draw_duration > draw_duration_estimate) |
| 987 draw_duration_underestimate = draw_duration - draw_duration_estimate; |
| 988 else |
| 989 draw_duration_overestimate = draw_duration_estimate - draw_duration; |
| 990 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration", |
| 991 draw_duration, |
| 992 base::TimeDelta::FromMilliseconds(1), |
| 993 base::TimeDelta::FromMilliseconds(100), |
| 994 50); |
| 995 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate", |
| 996 draw_duration_underestimate, |
| 997 base::TimeDelta::FromMilliseconds(1), |
| 998 base::TimeDelta::FromMilliseconds(100), |
| 999 50); |
| 1000 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate", |
| 1001 draw_duration_overestimate, |
| 1002 base::TimeDelta::FromMilliseconds(1), |
| 1003 base::TimeDelta::FromMilliseconds(100), |
| 1004 50); |
| 1005 } |
| 1006 |
974 // Update the tile state after drawing. This prevents manage tiles from | 1007 // Update the tile state after drawing. This prevents manage tiles from |
975 // being in the critical path for getting things on screen, but still | 1008 // being in the critical path for getting things on screen, but still |
976 // makes sure that tile state is updated on a semi-regular basis. | 1009 // makes sure that tile state is updated on a semi-regular basis. |
977 if (layer_tree_host_impl_->settings().impl_side_painting) | 1010 if (layer_tree_host_impl_->settings().impl_side_painting) |
978 layer_tree_host_impl_->ManageTiles(); | 1011 layer_tree_host_impl_->ManageTiles(); |
979 | 1012 |
980 return result; | 1013 return result; |
981 } | 1014 } |
982 | 1015 |
983 void ThreadProxy::AcquireLayerTextures() { | 1016 void ThreadProxy::AcquireLayerTextures() { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 return ScheduledActionDrawAndSwapInternal(true); | 1062 return ScheduledActionDrawAndSwapInternal(true); |
1030 } | 1063 } |
1031 | 1064 |
1032 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) { | 1065 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) { |
1033 if (current_resource_update_controller_on_impl_thread_) | 1066 if (current_resource_update_controller_on_impl_thread_) |
1034 current_resource_update_controller_on_impl_thread_ | 1067 current_resource_update_controller_on_impl_thread_ |
1035 ->PerformMoreUpdates(time); | 1068 ->PerformMoreUpdates(time); |
1036 layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame(); | 1069 layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame(); |
1037 } | 1070 } |
1038 | 1071 |
| 1072 base::TimeDelta ThreadProxy::DrawDurationEstimate() { |
| 1073 base::TimeDelta historical_estimate = |
| 1074 draw_duration_history_.Percentile(kDrawDurationEstimationPercentile); |
| 1075 base::TimeDelta padding = base::TimeDelta::FromMicroseconds( |
| 1076 kDrawDurationEstimatePaddingInMicroseconds); |
| 1077 return historical_estimate + padding; |
| 1078 } |
| 1079 |
1039 void ThreadProxy::ReadyToFinalizeTextureUpdates() { | 1080 void ThreadProxy::ReadyToFinalizeTextureUpdates() { |
1040 DCHECK(IsImplThread()); | 1081 DCHECK(IsImplThread()); |
1041 scheduler_on_impl_thread_->FinishCommit(); | 1082 scheduler_on_impl_thread_->FinishCommit(); |
1042 } | 1083 } |
1043 | 1084 |
1044 void ThreadProxy::DidCommitAndDrawFrame() { | 1085 void ThreadProxy::DidCommitAndDrawFrame() { |
1045 DCHECK(IsMainThread()); | 1086 DCHECK(IsMainThread()); |
1046 if (!layer_tree_host_) | 1087 if (!layer_tree_host_) |
1047 return; | 1088 return; |
1048 layer_tree_host_->DidCommitAndDrawFrame(); | 1089 layer_tree_host_->DidCommitAndDrawFrame(); |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1383 !layer_tree_host_impl_->pending_tree()) { | 1424 !layer_tree_host_impl_->pending_tree()) { |
1384 TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation", | 1425 TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation", |
1385 TRACE_EVENT_SCOPE_THREAD); | 1426 TRACE_EVENT_SCOPE_THREAD); |
1386 DCHECK(layer_tree_host_impl_->settings().impl_side_painting); | 1427 DCHECK(layer_tree_host_impl_->settings().impl_side_painting); |
1387 completion_event_for_commit_held_on_tree_activation_->Signal(); | 1428 completion_event_for_commit_held_on_tree_activation_->Signal(); |
1388 completion_event_for_commit_held_on_tree_activation_ = NULL; | 1429 completion_event_for_commit_held_on_tree_activation_ = NULL; |
1389 } | 1430 } |
1390 } | 1431 } |
1391 | 1432 |
1392 } // namespace cc | 1433 } // namespace cc |
OLD | NEW |