| 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());
|
|
|
|
|