Index: cc/trees/thread_proxy.cc |
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc |
index d112a7065855806883a118980d54c9ee84d5e723..cc009d59a8613045c4d53d7874e09b9457ea17d5 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), |
@@ -117,63 +118,58 @@ 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; |
- // 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, |
brianderson
2013/07/18 02:02:49
This method has been made part of ForceCommitForRe
|
- 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() { |
@@ -373,14 +369,32 @@ 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(); |
+ 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. |
+ 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( |
@@ -394,7 +408,17 @@ 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); |
+ |
+ if (!has_pending_tree && !deferred_start_commit_on_impl_thread_.is_null()) { |
+ Proxy::ImplThreadTaskRunner()->PostTask( |
+ FROM_HERE, |
+ deferred_start_commit_on_impl_thread_); |
+ deferred_start_commit_on_impl_thread_.Reset(); |
+ } |
} |
void ThreadProxy::SetNeedsCommitOnImplThread() { |
@@ -630,6 +654,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 = |
@@ -638,6 +663,8 @@ 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( |
@@ -786,8 +813,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()); |
@@ -797,9 +822,26 @@ void ThreadProxy::StartCommitOnImplThread( |
if (!layer_tree_host_impl_) { |
TRACE_EVENT0("cc", "EarlyOut_NoLayerTree"); |
completion->Signal(); |
+ |
+ return; |
+ } |
+ |
+ // We defer forced commits while there is a pending tree here. |
brianderson
2013/07/18 02:02:49
This code is no longer needed to make composite an
|
+ if (layer_tree_host_impl_->pending_tree()) { |
+ NOTREACHED(); |
+ TRACE_EVENT0("cc", "EarlyOut_DeferringDueToPendingTree"); |
+ DCHECK(deferred_start_commit_on_impl_thread_.is_null()); |
+ deferred_start_commit_on_impl_thread_ = |
+ base::Bind(&ThreadProxy::StartCommitOnImplThread, |
+ impl_thread_weak_ptr_, |
+ completion, |
+ raw_queue, |
+ offscreen_context_provider); |
return; |
} |
+ scoped_ptr<ResourceUpdateQueue> queue(raw_queue); |
+ |
if (offscreen_context_provider.get()) |
offscreen_context_provider->BindToCurrentThread(); |
layer_tree_host_impl_->resource_provider()-> |
@@ -855,9 +897,6 @@ void ThreadProxy::ScheduledActionCommit() { |
layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get()); |
layer_tree_host_impl_->CommitComplete(); |
- 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 && |
@@ -879,6 +918,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()); |
} |
@@ -904,11 +947,12 @@ void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() { |
main_thread_weak_ptr_)); |
} |
-ScheduledActionDrawAndSwapResult |
-ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) { |
+DrawSwapReadbackResult |
+ThreadProxy::ScheduledActionDrawSwapReadbackInternal( |
+ bool forced_draw, bool swap_requested, bool readback_requested) { |
TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap"); |
- ScheduledActionDrawAndSwapResult result; |
+ DrawSwapReadbackResult result; |
result.did_draw = false; |
result.did_swap = false; |
DCHECK(IsImplThread()); |
@@ -920,19 +964,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); |
@@ -948,12 +979,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)) { |
@@ -962,15 +993,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, |
@@ -979,20 +1008,19 @@ 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 = |
+ 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) |
@@ -1084,21 +1112,38 @@ void ThreadProxy::ScheduledActionAcquireLayerTexturesForMainThread() { |
texture_acquisition_completion_event_on_impl_thread_ = NULL; |
} |
-ScheduledActionDrawAndSwapResult |
+DrawSwapReadbackResult |
ThreadProxy::ScheduledActionDrawAndSwapIfPossible() { |
- return ScheduledActionDrawAndSwapInternal(false); |
+ bool forced_draw = false; |
+ bool swap_requested = true; |
+ bool readback_requested = false; |
+ return ScheduledActionDrawSwapReadbackInternal( |
+ forced_draw, swap_requested, readback_requested); |
} |
-ScheduledActionDrawAndSwapResult |
+DrawSwapReadbackResult |
ThreadProxy::ScheduledActionDrawAndSwapForced() { |
- return ScheduledActionDrawAndSwapInternal(true); |
+ bool forced_draw = true; |
+ bool swap_requested = true; |
+ bool readback_requested = false; |
+ return ScheduledActionDrawSwapReadbackInternal( |
+ forced_draw, swap_requested, readback_requested); |
+} |
+ |
+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(); |
} |
base::TimeDelta ThreadProxy::DrawDurationEstimate() { |
@@ -1119,6 +1164,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(); |
@@ -1196,6 +1249,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()); |