Index: cc/trees/thread_proxy.cc |
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc |
index 31a497ab267419fb189fadd24095c8e57df86438..912e244a0fa6b498a76252f7988e117f81e007ca 100644 |
--- a/cc/trees/thread_proxy.cc |
+++ b/cc/trees/thread_proxy.cc |
@@ -77,6 +77,7 @@ ThreadProxy::ThreadProxy( |
manage_tiles_pending_(false), |
weak_factory_on_impl_thread_(this), |
weak_factory_(this), |
+ frame_did_draw_(false), |
begin_frame_sent_to_main_thread_completion_event_on_impl_thread_(NULL), |
readback_request_on_impl_thread_(NULL), |
commit_completion_event_on_impl_thread_(NULL), |
@@ -123,19 +124,27 @@ bool ThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) { |
return false; |
} |
- // Perform a synchronous commit. |
+ // Perform a synchronous commit with an associated readback. |
+ ReadbackRequest request; |
+ request.rect = rect; |
+ request.pixels = pixels; |
{ |
DebugScopedSetMainThreadBlocked main_thread_blocked(this); |
CompletionEvent begin_frame_sent_to_main_thread_completion; |
Proxy::ImplThreadTaskRunner()->PostTask( |
FROM_HERE, |
- base::Bind(&ThreadProxy::ForceCommitOnImplThread, |
+ base::Bind(&ThreadProxy::ForceCommitForReadbackOnImplThread, |
impl_thread_weak_ptr_, |
- &begin_frame_sent_to_main_thread_completion)); |
+ &begin_frame_sent_to_main_thread_completion, |
+ &request)); |
begin_frame_sent_to_main_thread_completion.Wait(); |
} |
in_composite_and_readback_ = true; |
+ // This is the forced commit. |
+ // Note: The Impl thread also queues a separate BeginFrameOnMainThread on the |
+ // main thread, which will be called after this CompositeAndReadback |
+ // completes, to replace the forced commit. |
BeginFrameOnMainThread(scoped_ptr<BeginFrameAndCommitState>()); |
in_composite_and_readback_ = false; |
@@ -143,48 +152,35 @@ bool ThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) { |
// that it made. |
can_cancel_commit_ = false; |
- // Perform a synchronous readback. |
- ReadbackRequest request; |
- request.rect = rect; |
- request.pixels = pixels; |
- { |
- DebugScopedSetMainThreadBlocked main_thread_blocked(this); |
- Proxy::ImplThreadTaskRunner()->PostTask( |
- FROM_HERE, |
- base::Bind(&ThreadProxy::RequestReadbackOnImplThread, |
- impl_thread_weak_ptr_, |
- &request)); |
- request.completion.Wait(); |
- } |
+ request.completion.Wait(); |
return request.success; |
} |
-void ThreadProxy::ForceCommitOnImplThread(CompletionEvent* completion) { |
- TRACE_EVENT0("cc", "ThreadProxy::ForceCommitOnImplThread"); |
+void ThreadProxy::ForceCommitForReadbackOnImplThread( |
+ CompletionEvent* begin_frame_sent_completion, |
+ ReadbackRequest* request) { |
+ TRACE_EVENT0("cc", "ThreadProxy::ForceCommitForReadbackOnImplThread"); |
DCHECK(IsImplThread()); |
DCHECK(!begin_frame_sent_to_main_thread_completion_event_on_impl_thread_); |
- |
- scheduler_on_impl_thread_->SetNeedsForcedCommit(); |
- if (scheduler_on_impl_thread_->CommitPending()) { |
- completion->Signal(); |
- return; |
- } |
- |
- begin_frame_sent_to_main_thread_completion_event_on_impl_thread_ = completion; |
-} |
- |
-void ThreadProxy::RequestReadbackOnImplThread(ReadbackRequest* request) { |
- DCHECK(Proxy::IsImplThread()); |
DCHECK(!readback_request_on_impl_thread_); |
+ |
if (!layer_tree_host_impl_) { |
+ begin_frame_sent_completion->Signal(); |
request->success = false; |
request->completion.Signal(); |
return; |
} |
readback_request_on_impl_thread_ = request; |
- scheduler_on_impl_thread_->SetNeedsRedraw(); |
- scheduler_on_impl_thread_->SetNeedsForcedRedraw(); |
+ |
+ scheduler_on_impl_thread_->SetNeedsForcedCommitForReadback(); |
+ if (scheduler_on_impl_thread_->CommitPending()) { |
+ begin_frame_sent_completion->Signal(); |
+ return; |
+ } |
+ |
+ begin_frame_sent_to_main_thread_completion_event_on_impl_thread_ = |
+ begin_frame_sent_completion; |
} |
void ThreadProxy::FinishAllRendering() { |
@@ -393,14 +389,35 @@ void ThreadProxy::SetNeedsBeginFrameOnImplThread(bool enable) { |
TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginFrameOnImplThread", |
"enable", enable); |
layer_tree_host_impl_->SetNeedsBeginFrame(enable); |
+ layer_tree_host_impl_->UpdateBackgroundAnimateTicking(!enable); |
} |
void ThreadProxy::BeginFrameOnImplThread(const BeginFrameArgs& args) { |
DCHECK(IsImplThread()); |
TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnImplThread"); |
+ |
+ base::TimeTicks monotonic_time = |
+ layer_tree_host_impl_->CurrentFrameTimeTicks(); |
+ base::Time wall_clock_time = layer_tree_host_impl_->CurrentFrameTime(); |
+ if (layer_tree_host_impl_->active_tree()->root_layer()) |
+ layer_tree_host_impl_->Animate(monotonic_time, wall_clock_time); |
+ |
+ // Reinitialize for the current frame. |
+ frame_did_draw_ = false; |
+ |
scheduler_on_impl_thread_->BeginFrame(args); |
} |
+void ThreadProxy::DidBeginFrameDeadlineOnImplThread() { |
+ // Do not start animations if we skip drawing the frame to avoid |
+ // checkerboarding. |
+ if (layer_tree_host_impl_->active_tree()->root_layer()) { |
+ layer_tree_host_impl_->UpdateAnimationState( |
+ frame_did_draw_ || !layer_tree_host_impl_->CanDraw()); |
+ } |
+ layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame(); |
+} |
+ |
void ThreadProxy::OnCanDrawStateChanged(bool can_draw) { |
DCHECK(IsImplThread()); |
TRACE_EVENT1( |
@@ -410,11 +427,20 @@ void ThreadProxy::OnCanDrawStateChanged(bool can_draw) { |
!scheduler_on_impl_thread_->WillDrawIfNeeded()); |
} |
+void ThreadProxy::NotifyReadyToActivate() { |
+ TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate"); |
+ scheduler_on_impl_thread_->NotifyReadyToActivate(); |
+} |
+ |
void ThreadProxy::OnHasPendingTreeStateChanged(bool has_pending_tree) { |
DCHECK(IsImplThread()); |
TRACE_EVENT1("cc", "ThreadProxy::OnHasPendingTreeStateChanged", |
"has_pending_tree", has_pending_tree); |
- scheduler_on_impl_thread_->SetHasPendingTree(has_pending_tree); |
+ scheduler_on_impl_thread_->SetHasTrees( |
+ has_pending_tree, |
+ layer_tree_host_impl_->active_tree() |
+ ? !layer_tree_host_impl_->active_tree()->root_layer() |
+ : true); |
} |
void ThreadProxy::SetNeedsCommitOnImplThread() { |
@@ -668,6 +694,7 @@ void ThreadProxy::ScheduledActionSendBeginFrameToMainThread() { |
TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionSendBeginFrameToMainThread"); |
scoped_ptr<BeginFrameAndCommitState> begin_frame_state( |
new BeginFrameAndCommitState); |
+ |
begin_frame_state->monotonic_frame_begin_time = |
layer_tree_host_impl_->CurrentPhysicalTimeTicks(); |
begin_frame_state->scroll_info = |
@@ -676,6 +703,7 @@ void ThreadProxy::ScheduledActionSendBeginFrameToMainThread() { |
if (!layer_tree_host_impl_->settings().impl_side_painting) { |
DCHECK_GT(layer_tree_host_impl_->memory_allocation_limit_bytes(), 0u); |
} |
+ |
begin_frame_state->memory_allocation_limit_bytes = |
layer_tree_host_impl_->memory_allocation_limit_bytes(); |
Proxy::MainThreadTaskRunner()->PostTask( |
@@ -851,8 +879,6 @@ void ThreadProxy::StartCommitOnImplThread( |
CompletionEvent* completion, |
ResourceUpdateQueue* raw_queue, |
scoped_refptr<cc::ContextProvider> offscreen_context_provider) { |
- scoped_ptr<ResourceUpdateQueue> queue(raw_queue); |
- |
TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread"); |
DCHECK(!commit_completion_event_on_impl_thread_); |
DCHECK(IsImplThread() && IsMainThreadBlocked()); |
@@ -862,9 +888,12 @@ void ThreadProxy::StartCommitOnImplThread( |
if (!layer_tree_host_impl_) { |
TRACE_EVENT0("cc", "EarlyOut_NoLayerTree"); |
completion->Signal(); |
+ |
return; |
} |
+ scoped_ptr<ResourceUpdateQueue> queue(raw_queue); |
+ |
if (offscreen_context_provider.get()) |
offscreen_context_provider->BindToCurrentThread(); |
layer_tree_host_impl_->resource_provider()-> |
@@ -931,9 +960,6 @@ void ThreadProxy::ScheduledActionCommit() { |
SetInputThrottledUntilCommitOnImplThread(false); |
- layer_tree_host_impl_->UpdateBackgroundAnimateTicking( |
- !scheduler_on_impl_thread_->WillDrawIfNeeded()); |
- |
next_frame_is_newly_committed_frame_on_impl_thread_ = true; |
if (layer_tree_host_->settings().impl_side_painting && |
@@ -955,6 +981,10 @@ void ThreadProxy::ScheduledActionCommit() { |
begin_frame_to_commit_duration_history_.InsertSample( |
commit_complete_time_ - begin_frame_sent_to_main_thread_time_); |
+ // The commit may have added animations, requiring us to start |
+ // background ticking. |
+ layer_tree_host_impl_->UpdateBackgroundAnimateTicking( |
+ !scheduler_on_impl_thread_->WillDrawIfNeeded()); |
// SetVisible kicks off the next scheduler action, so this must be last. |
scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); |
} |
@@ -965,10 +995,10 @@ void ThreadProxy::ScheduledActionUpdateVisibleTiles() { |
layer_tree_host_impl_->UpdateVisibleTiles(); |
} |
-void ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded() { |
+void ThreadProxy::ScheduledActionActivatePendingTree() { |
DCHECK(IsImplThread()); |
- TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded"); |
- layer_tree_host_impl_->ActivatePendingTreeIfNeeded(); |
+ TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTree"); |
+ layer_tree_host_impl_->ActivatePendingTree(); |
} |
void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() { |
@@ -979,12 +1009,13 @@ void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() { |
main_thread_weak_ptr_)); |
} |
-ScheduledActionDrawAndSwapResult |
-ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) { |
- TRACE_EVENT1( |
- "cc", "ThreadProxy::ScheduledActionDrawAndSwap", "forced", forced_draw); |
+DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawSwapReadbackInternal( |
+ bool forced_draw, |
+ bool swap_requested, |
+ bool readback_requested) { |
+ TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawSwapReadback"); |
- ScheduledActionDrawAndSwapResult result; |
+ DrawSwapReadbackResult result; |
result.did_draw = false; |
result.did_swap = false; |
DCHECK(IsImplThread()); |
@@ -996,19 +1027,6 @@ ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) { |
if (!layer_tree_host_impl_->renderer()) |
return result; |
- base::TimeTicks monotonic_time = |
- layer_tree_host_impl_->CurrentFrameTimeTicks(); |
- base::Time wall_clock_time = layer_tree_host_impl_->CurrentFrameTime(); |
- |
- // TODO(enne): This should probably happen post-animate. |
- if (layer_tree_host_impl_->pending_tree()) { |
- layer_tree_host_impl_->ActivatePendingTreeIfNeeded(); |
- if (layer_tree_host_impl_->pending_tree()) |
- layer_tree_host_impl_->pending_tree()->UpdateDrawProperties(); |
- } |
- layer_tree_host_impl_->Animate(monotonic_time, wall_clock_time); |
- layer_tree_host_impl_->UpdateBackgroundAnimateTicking(false); |
- |
base::TimeTicks start_time = base::TimeTicks::HighResNow(); |
base::TimeDelta draw_duration_estimate = DrawDurationEstimate(); |
base::AutoReset<bool> mark_inside(&inside_draw_, true); |
@@ -1024,12 +1042,12 @@ ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) { |
// DrawLayers() depends on the result of PrepareToDraw(), it is guarded on |
// CanDraw() as well. |
- bool drawing_for_readback = !!readback_request_on_impl_thread_; |
+ bool drawing_for_readback = |
+ readback_requested && !!readback_request_on_impl_thread_; |
bool can_do_readback = layer_tree_host_impl_->renderer()->CanReadPixels(); |
LayerTreeHostImpl::FrameData frame; |
bool draw_frame = false; |
- bool start_ready_animations = true; |
if (layer_tree_host_impl_->CanDraw() && |
(!drawing_for_readback || can_do_readback)) { |
@@ -1038,15 +1056,13 @@ ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) { |
if (drawing_for_readback) |
readback_rect = readback_request_on_impl_thread_->rect; |
- // Do not start animations if we skip drawing the frame to avoid |
- // checkerboarding. |
if (layer_tree_host_impl_->PrepareToDraw(&frame, readback_rect) || |
forced_draw) |
draw_frame = true; |
- else |
- start_ready_animations = false; |
} |
+ frame_did_draw_ = draw_frame; |
+ |
if (draw_frame) { |
layer_tree_host_impl_->DrawLayers( |
&frame, |
@@ -1055,20 +1071,18 @@ ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) { |
} |
layer_tree_host_impl_->DidDrawAllLayers(frame); |
- layer_tree_host_impl_->UpdateAnimationState(start_ready_animations); |
- |
// Check for a pending CompositeAndReadback. |
- if (readback_request_on_impl_thread_) { |
- readback_request_on_impl_thread_->success = false; |
+ if (drawing_for_readback) { |
+ result.did_readback = false; |
if (draw_frame) { |
layer_tree_host_impl_->Readback(readback_request_on_impl_thread_->pixels, |
readback_request_on_impl_thread_->rect); |
- readback_request_on_impl_thread_->success = |
- !layer_tree_host_impl_->IsContextLost(); |
+ result.did_readback = !layer_tree_host_impl_->IsContextLost(); |
} |
+ readback_request_on_impl_thread_->success = result.did_readback; |
readback_request_on_impl_thread_->completion.Signal(); |
readback_request_on_impl_thread_ = NULL; |
- } else if (draw_frame) { |
+ } else if (draw_frame && swap_requested) { |
result.did_swap = layer_tree_host_impl_->SwapBuffers(frame); |
if (frame.contains_incomplete_tile) |
@@ -1161,21 +1175,34 @@ void ThreadProxy::ScheduledActionAcquireLayerTexturesForMainThread() { |
texture_acquisition_completion_event_on_impl_thread_ = NULL; |
} |
-ScheduledActionDrawAndSwapResult |
-ThreadProxy::ScheduledActionDrawAndSwapIfPossible() { |
- return ScheduledActionDrawAndSwapInternal(false); |
+DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndSwapIfPossible() { |
+ bool forced_draw = false; |
+ bool swap_requested = true; |
+ bool readback_requested = false; |
+ return ScheduledActionDrawSwapReadbackInternal( |
+ forced_draw, swap_requested, readback_requested); |
+} |
+ |
+DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndSwapForced() { |
+ bool forced_draw = true; |
+ bool swap_requested = true; |
+ bool readback_requested = false; |
+ return ScheduledActionDrawSwapReadbackInternal( |
+ forced_draw, swap_requested, readback_requested); |
} |
-ScheduledActionDrawAndSwapResult |
-ThreadProxy::ScheduledActionDrawAndSwapForced() { |
- return ScheduledActionDrawAndSwapInternal(true); |
+DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndReadback() { |
+ bool forced_draw = true; |
+ bool swap_requested = false; |
+ bool readback_requested = true; |
+ return ScheduledActionDrawSwapReadbackInternal( |
+ forced_draw, swap_requested, readback_requested); |
} |
void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) { |
if (current_resource_update_controller_on_impl_thread_) |
- current_resource_update_controller_on_impl_thread_ |
- ->PerformMoreUpdates(time); |
- layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame(); |
+ current_resource_update_controller_on_impl_thread_->PerformMoreUpdates( |
+ time); |
} |
base::TimeDelta ThreadProxy::DrawDurationEstimate() { |
@@ -1196,6 +1223,14 @@ base::TimeDelta ThreadProxy::CommitToActivateDurationEstimate() { |
kCommitAndActivationDurationEstimationPercentile); |
} |
+void ThreadProxy::PostBeginFrameDeadline(const base::Closure& closure, |
+ base::TimeTicks deadline) { |
+ base::TimeDelta delta = deadline - base::TimeTicks::Now(); |
+ if (delta <= base::TimeDelta()) |
+ delta = base::TimeDelta(); |
+ Proxy::ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, closure, delta); |
+} |
+ |
void ThreadProxy::ReadyToFinalizeTextureUpdates() { |
DCHECK(IsImplThread()); |
scheduler_on_impl_thread_->FinishCommit(); |
@@ -1266,6 +1301,8 @@ void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) { |
layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this); |
const LayerTreeSettings& settings = layer_tree_host_->settings(); |
SchedulerSettings scheduler_settings; |
+ scheduler_settings.deadline_scheduling_enabled = |
+ settings.deadline_scheduling_enabled; |
scheduler_settings.impl_side_painting = settings.impl_side_painting; |
scheduler_settings.timeout_and_draw_when_animation_checkerboards = |
settings.timeout_and_draw_when_animation_checkerboards; |
@@ -1273,6 +1310,7 @@ void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) { |
settings.using_synchronous_renderer_compositor; |
scheduler_settings.throttle_frame_production = |
settings.throttle_frame_production; |
+ scheduler_settings.use_begin_frame_workaround_for_crbug_249806 = true; |
scheduler_on_impl_thread_ = Scheduler::Create(this, scheduler_settings); |
scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); |