[go: nahoru, domu]

blob: 2a7e31a17af299e35b832d1b36c8106d56d179c8 [file] [log] [blame]
khushalsagar0a226af2015-12-09 10:30:201// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cc/trees/proxy_impl.h"
6
sunnypsc7d72f32017-04-11 19:07:507#include <string.h>
8
khushalsagar0a226af2015-12-09 10:30:209#include <algorithm>
10#include <string>
11
12#include "base/auto_reset.h"
sunnypsc7d72f32017-04-11 19:07:5013#include "base/debug/alias.h"
14#include "base/debug/dump_without_crashing.h"
danakj60bc3bc2016-04-09 00:24:4815#include "base/memory/ptr_util.h"
khushalsagar0a226af2015-12-09 10:30:2016#include "base/trace_event/trace_event.h"
17#include "base/trace_event/trace_event_argument.h"
18#include "base/trace_event/trace_event_synthetic_delay.h"
chrishtr82b5d9502017-03-20 18:25:3319#include "cc/base/devtools_instrumentation.h"
20#include "cc/benchmarks/benchmark_instrumentation.h"
mdjones2ee41afd2016-10-27 16:50:2021#include "cc/input/browser_controls_offset_manager.h"
khushalsagar0a226af2015-12-09 10:30:2022#include "cc/output/context_provider.h"
danakjc7afae52017-06-20 21:12:4123#include "cc/output/layer_tree_frame_sink.h"
khushalsagar0a226af2015-12-09 10:30:2024#include "cc/scheduler/compositor_timing_history.h"
danakj15ec5242016-06-15 22:13:3725#include "cc/scheduler/delay_based_time_source.h"
khushalsagare0e4486e2017-01-25 03:15:0326#include "cc/trees/layer_tree_host.h"
khushalsagar0a226af2015-12-09 10:30:2027#include "cc/trees/layer_tree_impl.h"
loysoc601b7b82016-11-10 02:56:4428#include "cc/trees/mutator_host.h"
khushalsagar12020cd42016-11-21 09:22:4829#include "cc/trees/proxy_main.h"
khushalsagar0a226af2015-12-09 10:30:2030#include "cc/trees/task_runner_provider.h"
31#include "gpu/command_buffer/client/gles2_interface.h"
32
33namespace cc {
34
35namespace {
36
37// Measured in seconds.
38const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
39
40unsigned int nextBeginFrameId = 0;
41
42} // namespace
43
khushalsagar12020cd42016-11-21 09:22:4844ProxyImpl::ProxyImpl(base::WeakPtr<ProxyMain> proxy_main_weak_ptr,
khushalsagare0e4486e2017-01-25 03:15:0345 LayerTreeHost* layer_tree_host,
enne2b0ad682016-09-21 01:44:4746 TaskRunnerProvider* task_runner_provider)
khushalsagarcebe4942016-09-07 23:27:0147 : layer_tree_host_id_(layer_tree_host->GetId()),
sunnyps2237c9b2016-05-20 22:25:0648 commit_completion_waits_for_activation_(false),
khushalsagar0a226af2015-12-09 10:30:2049 commit_completion_event_(nullptr),
sunnyps2237c9b2016-05-20 22:25:0650 activation_completion_event_(nullptr),
khushalsagar0a226af2015-12-09 10:30:2051 next_frame_is_newly_committed_frame_(false),
52 inside_draw_(false),
53 input_throttled_until_commit_(false),
54 task_runner_provider_(task_runner_provider),
55 smoothness_priority_expiration_notifier_(
56 task_runner_provider->ImplThreadTaskRunner(),
57 base::Bind(&ProxyImpl::RenewTreePriority, base::Unretained(this)),
khushalsagar0f081c42015-12-16 07:04:2058 base::TimeDelta::FromSecondsD(
khushalsagar0a226af2015-12-09 10:30:2059 kSmoothnessTakesPriorityExpirationDelay)),
khushalsagar0a226af2015-12-09 10:30:2060 rendering_stats_instrumentation_(
61 layer_tree_host->rendering_stats_instrumentation()),
khushalsagar12020cd42016-11-21 09:22:4862 proxy_main_weak_ptr_(proxy_main_weak_ptr) {
khushalsagar0a226af2015-12-09 10:30:2063 TRACE_EVENT0("cc", "ProxyImpl::ProxyImpl");
64 DCHECK(IsImplThread());
65 DCHECK(IsMainThreadBlocked());
66
danakj94b7e4f2016-07-20 01:49:3867 // Double checking we set this correctly since double->int truncations are
68 // silent and have been done mistakenly: crbug.com/568120.
69 DCHECK(!smoothness_priority_expiration_notifier_.delay().is_zero());
70
khushalsagar0a226af2015-12-09 10:30:2071 layer_tree_host_impl_ = layer_tree_host->CreateLayerTreeHostImpl(this);
khushalsagarcebe4942016-09-07 23:27:0172 const LayerTreeSettings& settings = layer_tree_host->GetSettings();
khushalsagar0a226af2015-12-09 10:30:2073
khushalsagarcebe4942016-09-07 23:27:0174 SchedulerSettings scheduler_settings(settings.ToSchedulerSettings());
khushalsagar0a226af2015-12-09 10:30:2075
danakj60bc3bc2016-04-09 00:24:4876 std::unique_ptr<CompositorTimingHistory> compositor_timing_history(
briandersonbb917dd2016-02-20 05:21:1477 new CompositorTimingHistory(
78 scheduler_settings.using_synchronous_renderer_compositor,
79 CompositorTimingHistory::RENDERER_UMA,
80 rendering_stats_instrumentation_));
enne2b0ad682016-09-21 01:44:4781 scheduler_.reset(new Scheduler(this, scheduler_settings, layer_tree_host_id_,
enne5593b842016-09-01 20:21:1682 task_runner_provider_->ImplThreadTaskRunner(),
enne2b0ad682016-09-21 01:44:4783 std::move(compositor_timing_history)));
khushalsagar0a226af2015-12-09 10:30:2084
85 DCHECK_EQ(scheduler_->visible(), layer_tree_host_impl_->visible());
86}
87
88ProxyImpl::BlockedMainCommitOnly::BlockedMainCommitOnly()
89 : layer_tree_host(nullptr) {}
90
91ProxyImpl::BlockedMainCommitOnly::~BlockedMainCommitOnly() {}
92
93ProxyImpl::~ProxyImpl() {
94 TRACE_EVENT0("cc", "ProxyImpl::~ProxyImpl");
95 DCHECK(IsImplThread());
96 DCHECK(IsMainThreadBlocked());
97
sunnypsda928f0a2016-10-08 00:32:5398 // Prevent the scheduler from performing actions while we're in an
99 // inconsistent state.
100 scheduler_->Stop();
danakjc7afae52017-06-20 21:12:41101 // Take away the LayerTreeFrameSink before destroying things so it doesn't
danakj1120f4c2016-09-15 02:05:32102 // try to call into its client mid-shutdown.
danakjc7afae52017-06-20 21:12:41103 layer_tree_host_impl_->ReleaseLayerTreeFrameSink();
khushalsagar0a226af2015-12-09 10:30:20104 scheduler_ = nullptr;
khushalsagar0a226af2015-12-09 10:30:20105 layer_tree_host_impl_ = nullptr;
106 // We need to explicitly shutdown the notifier to destroy any weakptrs it is
107 // holding while still on the compositor thread. This also ensures any
108 // callbacks holding a ProxyImpl pointer are cancelled.
109 smoothness_priority_expiration_notifier_.Shutdown();
110}
111
flackrf54e9b42016-05-31 15:20:10112void ProxyImpl::InitializeMutatorOnImpl(
113 std::unique_ptr<LayerTreeMutator> mutator) {
114 TRACE_EVENT0("cc,compositor-worker", "ProxyImpl::InitializeMutatorOnImpl");
115 DCHECK(IsImplThread());
116 layer_tree_host_impl_->SetLayerTreeMutator(std::move(mutator));
117}
118
mdjones2ee41afd2016-10-27 16:50:20119void ProxyImpl::UpdateBrowserControlsStateOnImpl(
120 BrowserControlsState constraints,
121 BrowserControlsState current,
122 bool animate) {
khushalsagar0a226af2015-12-09 10:30:20123 DCHECK(IsImplThread());
mdjones2ee41afd2016-10-27 16:50:20124 layer_tree_host_impl_->browser_controls_manager()->UpdateBrowserControlsState(
khushalsagar0a226af2015-12-09 10:30:20125 constraints, current, animate);
126}
127
danakjc7afae52017-06-20 21:12:41128void ProxyImpl::InitializeLayerTreeFrameSinkOnImpl(
129 LayerTreeFrameSink* layer_tree_frame_sink,
samans44b6dfc2017-04-19 16:50:53130 base::WeakPtr<ProxyMain> proxy_main_frame_sink_bound_weak_ptr) {
danakjc7afae52017-06-20 21:12:41131 TRACE_EVENT0("cc", "ProxyImpl::InitializeLayerTreeFrameSinkOnImplThread");
khushalsagar0a226af2015-12-09 10:30:20132 DCHECK(IsImplThread());
133
samans44b6dfc2017-04-19 16:50:53134 proxy_main_frame_sink_bound_weak_ptr_ = proxy_main_frame_sink_bound_weak_ptr;
135
khushalsagar0a226af2015-12-09 10:30:20136 LayerTreeHostImpl* host_impl = layer_tree_host_impl_.get();
danakjc7afae52017-06-20 21:12:41137 bool success = host_impl->InitializeRenderer(layer_tree_frame_sink);
khushalsagar12020cd42016-11-21 09:22:48138 MainThreadTaskRunner()->PostTask(
danakjc7afae52017-06-20 21:12:41139 FROM_HERE, base::BindOnce(&ProxyMain::DidInitializeLayerTreeFrameSink,
tzik4604bb52017-04-13 21:50:22140 proxy_main_weak_ptr_, success));
khushalsagar0a226af2015-12-09 10:30:20141 if (success)
danakjc7afae52017-06-20 21:12:41142 scheduler_->DidCreateAndInitializeLayerTreeFrameSink();
khushalsagar0a226af2015-12-09 10:30:20143}
144
145void ProxyImpl::MainThreadHasStoppedFlingingOnImpl() {
146 DCHECK(IsImplThread());
147 layer_tree_host_impl_->MainThreadHasStoppedFlinging();
148}
149
150void ProxyImpl::SetInputThrottledUntilCommitOnImpl(bool is_throttled) {
151 DCHECK(IsImplThread());
152 if (is_throttled == input_throttled_until_commit_)
153 return;
154 input_throttled_until_commit_ = is_throttled;
155 RenewTreePriority();
156}
157
158void ProxyImpl::SetDeferCommitsOnImpl(bool defer_commits) const {
159 DCHECK(IsImplThread());
160 scheduler_->SetDeferCommits(defer_commits);
161}
162
163void ProxyImpl::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
164 DCHECK(IsImplThread());
danakje41d978a2016-09-19 21:09:28165 layer_tree_host_impl_->SetViewportDamage(damage_rect);
166 SetNeedsRedrawOnImplThread();
khushalsagar0a226af2015-12-09 10:30:20167}
168
169void ProxyImpl::SetNeedsCommitOnImpl() {
170 DCHECK(IsImplThread());
171 SetNeedsCommitOnImplThread();
172}
173
174void ProxyImpl::BeginMainFrameAbortedOnImpl(
175 CommitEarlyOutReason reason,
sunnypsad3235e2016-08-09 04:57:52176 base::TimeTicks main_thread_start_time,
177 std::vector<std::unique_ptr<SwapPromise>> swap_promises) {
khushalsagar0a226af2015-12-09 10:30:20178 TRACE_EVENT1("cc", "ProxyImpl::BeginMainFrameAbortedOnImplThread", "reason",
179 CommitEarlyOutReasonToString(reason));
180 DCHECK(IsImplThread());
181 DCHECK(scheduler_->CommitPending());
khushalsagar0a226af2015-12-09 10:30:20182
183 if (CommitEarlyOutHandledCommit(reason)) {
184 SetInputThrottledUntilCommitOnImpl(false);
khushalsagar0a226af2015-12-09 10:30:20185 }
sunnypsad3235e2016-08-09 04:57:52186 layer_tree_host_impl_->BeginMainFrameAborted(reason,
187 std::move(swap_promises));
khushalsagar0a226af2015-12-09 10:30:20188 scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time);
189 scheduler_->BeginMainFrameAborted(reason);
190}
191
khushalsagar0a226af2015-12-09 10:30:20192void ProxyImpl::SetVisibleOnImpl(bool visible) {
193 TRACE_EVENT1("cc", "ProxyImpl::SetVisibleOnImplThread", "visible", visible);
194 DCHECK(IsImplThread());
195 layer_tree_host_impl_->SetVisible(visible);
196 scheduler_->SetVisible(visible);
197}
198
danakjc7afae52017-06-20 21:12:41199void ProxyImpl::ReleaseLayerTreeFrameSinkOnImpl(CompletionEvent* completion) {
khushalsagar0a226af2015-12-09 10:30:20200 DCHECK(IsImplThread());
201
danakjc7afae52017-06-20 21:12:41202 // Unlike DidLoseLayerTreeFrameSinkOnImplThread, we don't need to call
203 // LayerTreeHost::DidLoseLayerTreeFrameSink since it already knows.
204 scheduler_->DidLoseLayerTreeFrameSink();
205 layer_tree_host_impl_->ReleaseLayerTreeFrameSink();
khushalsagar0a226af2015-12-09 10:30:20206 completion->Signal();
207}
208
209void ProxyImpl::FinishGLOnImpl(CompletionEvent* completion) {
210 TRACE_EVENT0("cc", "ProxyImpl::FinishGLOnImplThread");
211 DCHECK(IsImplThread());
danakjc7afae52017-06-20 21:12:41212 if (layer_tree_host_impl_->layer_tree_frame_sink()) {
khushalsagar0a226af2015-12-09 10:30:20213 ContextProvider* context_provider =
danakjc7afae52017-06-20 21:12:41214 layer_tree_host_impl_->layer_tree_frame_sink()->context_provider();
khushalsagar0a226af2015-12-09 10:30:20215 if (context_provider)
216 context_provider->ContextGL()->Finish();
217 }
218 completion->Signal();
219}
220
221void ProxyImpl::MainFrameWillHappenOnImplForTesting(
222 CompletionEvent* completion,
223 bool* main_frame_will_happen) {
224 DCHECK(IsImplThread());
danakjc7afae52017-06-20 21:12:41225 if (layer_tree_host_impl_->layer_tree_frame_sink()) {
khushalsagar0a226af2015-12-09 10:30:20226 *main_frame_will_happen = scheduler_->MainFrameForTestingWillHappen();
227 } else {
228 *main_frame_will_happen = false;
229 }
230 completion->Signal();
231}
232
Dan Elphick95929fd2017-06-13 09:15:07233void ProxyImpl::RequestBeginMainFrameNotExpected(bool new_state) {
234 DCHECK(IsImplThread());
235 DCHECK(scheduler_);
236 TRACE_EVENT1("cc", "ProxyImpl::RequestBeginMainFrameNotExpected", "new_state",
237 new_state);
238 scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(new_state);
239}
240
sunnypsc7d72f32017-04-11 19:07:50241// TODO(sunnyps): Remove this code once crbug.com/668892 is fixed.
242NOINLINE void ProxyImpl::DumpForBeginMainFrameHang() {
243 DCHECK(IsImplThread());
244 DCHECK(scheduler_);
245
sunnyps73f04652017-04-15 01:46:45246 auto state = base::MakeUnique<base::trace_event::TracedValue>();
247
248 state->SetBoolean("commit_completion_waits_for_activation",
249 commit_completion_waits_for_activation_);
250 state->SetBoolean("commit_completion_event", !!commit_completion_event_);
251 state->SetBoolean("activation_completion_event",
252 !!activation_completion_event_);
253
254 state->BeginDictionary("scheduler_state");
255 scheduler_->AsValueInto(state.get());
256 state->EndDictionary();
257
258 state->BeginDictionary("tile_manager_state");
259 layer_tree_host_impl_->tile_manager()->ActivationStateAsValueInto(
260 state.get());
261 state->EndDictionary();
262
263 char stack_string[50000] = "";
sunnypsc7d72f32017-04-11 19:07:50264 base::debug::Alias(&stack_string);
sunnyps73f04652017-04-15 01:46:45265 strncpy(stack_string, state->ToString().c_str(), arraysize(stack_string) - 1);
sunnypsc7d72f32017-04-11 19:07:50266
267 base::debug::DumpWithoutCrashing();
268}
269
danakj94b7e4f2016-07-20 01:49:38270void ProxyImpl::NotifyReadyToCommitOnImpl(
271 CompletionEvent* completion,
khushalsagare0e4486e2017-01-25 03:15:03272 LayerTreeHost* layer_tree_host,
danakj94b7e4f2016-07-20 01:49:38273 base::TimeTicks main_thread_start_time,
274 bool hold_commit_for_activation) {
275 TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToCommitOnImpl");
khushalsagar0a226af2015-12-09 10:30:20276 DCHECK(!commit_completion_event_);
277 DCHECK(IsImplThread() && IsMainThreadBlocked());
278 DCHECK(scheduler_);
279 DCHECK(scheduler_->CommitPending());
280
khushalsagar0a226af2015-12-09 10:30:20281 if (!layer_tree_host_impl_) {
282 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoLayerTree",
283 TRACE_EVENT_SCOPE_THREAD);
284 completion->Signal();
285 return;
286 }
287
288 // Ideally, we should inform to impl thread when BeginMainFrame is started.
289 // But, we can avoid a PostTask in here.
290 scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time);
sunnyps2237c9b2016-05-20 22:25:06291
danakj94b7e4f2016-07-20 01:49:38292 layer_tree_host_impl_->ReadyToCommit();
293
khushalsagar0a226af2015-12-09 10:30:20294 commit_completion_event_ = completion;
sunnyps2237c9b2016-05-20 22:25:06295 commit_completion_waits_for_activation_ = hold_commit_for_activation;
296
khushalsagar0a226af2015-12-09 10:30:20297 DCHECK(!blocked_main_commit().layer_tree_host);
298 blocked_main_commit().layer_tree_host = layer_tree_host;
299 scheduler_->NotifyReadyToCommit();
300}
301
danakjc7afae52017-06-20 21:12:41302void ProxyImpl::DidLoseLayerTreeFrameSinkOnImplThread() {
303 TRACE_EVENT0("cc", "ProxyImpl::DidLoseLayerTreeFrameSinkOnImplThread");
khushalsagar0a226af2015-12-09 10:30:20304 DCHECK(IsImplThread());
khushalsagar12020cd42016-11-21 09:22:48305 MainThreadTaskRunner()->PostTask(
danakjc7afae52017-06-20 21:12:41306 FROM_HERE, base::BindOnce(&ProxyMain::DidLoseLayerTreeFrameSink,
tzik4604bb52017-04-13 21:50:22307 proxy_main_weak_ptr_));
danakjc7afae52017-06-20 21:12:41308 scheduler_->DidLoseLayerTreeFrameSink();
khushalsagar0a226af2015-12-09 10:30:20309}
310
enne19c108582016-04-14 03:35:32311void ProxyImpl::SetBeginFrameSource(BeginFrameSource* source) {
danakjc7afae52017-06-20 21:12:41312 // During shutdown, destroying the LayerTreeFrameSink may unset the
danakjeaba8a82016-05-27 01:21:43313 // BeginFrameSource.
314 if (scheduler_) {
315 // TODO(enne): this overrides any preexisting begin frame source. Those
316 // other sources will eventually be removed and this will be the only path.
317 scheduler_->SetBeginFrameSource(source);
318 }
enne19c108582016-04-14 03:35:32319}
320
danakj9d124422016-10-14 03:15:08321void ProxyImpl::DidReceiveCompositorFrameAckOnImplThread() {
322 TRACE_EVENT0("cc,benchmark",
323 "ProxyImpl::DidReceiveCompositorFrameAckOnImplThread");
khushalsagar0a226af2015-12-09 10:30:20324 DCHECK(IsImplThread());
danakj9d124422016-10-14 03:15:08325 scheduler_->DidReceiveCompositorFrameAck();
khushalsagar12020cd42016-11-21 09:22:48326 MainThreadTaskRunner()->PostTask(
tzik4604bb52017-04-13 21:50:22327 FROM_HERE, base::BindOnce(&ProxyMain::DidReceiveCompositorFrameAck,
samans44b6dfc2017-04-19 16:50:53328 proxy_main_frame_sink_bound_weak_ptr_));
khushalsagar0a226af2015-12-09 10:30:20329}
330
khushalsagar0a226af2015-12-09 10:30:20331void ProxyImpl::OnCanDrawStateChanged(bool can_draw) {
332 TRACE_EVENT1("cc", "ProxyImpl::OnCanDrawStateChanged", "can_draw", can_draw);
333 DCHECK(IsImplThread());
334 scheduler_->SetCanDraw(can_draw);
335}
336
337void ProxyImpl::NotifyReadyToActivate() {
338 TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToActivate");
339 DCHECK(IsImplThread());
rogerm8aeea932017-04-19 21:26:57340 scheduler_->NotifyReadyToActivate();
khushalsagar0a226af2015-12-09 10:30:20341}
342
343void ProxyImpl::NotifyReadyToDraw() {
344 TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToDraw");
345 DCHECK(IsImplThread());
346 scheduler_->NotifyReadyToDraw();
347}
348
349void ProxyImpl::SetNeedsRedrawOnImplThread() {
350 TRACE_EVENT0("cc", "ProxyImpl::SetNeedsRedrawOnImplThread");
351 DCHECK(IsImplThread());
352 scheduler_->SetNeedsRedraw();
353}
354
khushalsagar0a226af2015-12-09 10:30:20355void ProxyImpl::SetNeedsOneBeginImplFrameOnImplThread() {
356 TRACE_EVENT0("cc", "ProxyImpl::SetNeedsOneBeginImplFrameOnImplThread");
357 DCHECK(IsImplThread());
358 scheduler_->SetNeedsOneBeginImplFrame();
359}
360
361void ProxyImpl::SetNeedsPrepareTilesOnImplThread() {
362 DCHECK(IsImplThread());
363 scheduler_->SetNeedsPrepareTiles();
364}
365
366void ProxyImpl::SetNeedsCommitOnImplThread() {
367 TRACE_EVENT0("cc", "ProxyImpl::SetNeedsCommitOnImplThread");
368 DCHECK(IsImplThread());
369 scheduler_->SetNeedsBeginMainFrame();
370}
371
372void ProxyImpl::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
373 TRACE_EVENT1("cc", "ProxyImpl::SetVideoNeedsBeginFrames",
374 "needs_begin_frames", needs_begin_frames);
375 DCHECK(IsImplThread());
376 // In tests the layer tree is destroyed after the scheduler is.
377 if (scheduler_)
378 scheduler_->SetVideoNeedsBeginFrames(needs_begin_frames);
379}
380
381void ProxyImpl::PostAnimationEventsToMainThreadOnImplThread(
loysoc601b7b82016-11-10 02:56:44382 std::unique_ptr<MutatorEvents> events) {
khushalsagar0a226af2015-12-09 10:30:20383 TRACE_EVENT0("cc", "ProxyImpl::PostAnimationEventsToMainThreadOnImplThread");
384 DCHECK(IsImplThread());
khushalsagar12020cd42016-11-21 09:22:48385 MainThreadTaskRunner()->PostTask(
tzik4604bb52017-04-13 21:50:22386 FROM_HERE, base::BindOnce(&ProxyMain::SetAnimationEvents,
387 proxy_main_weak_ptr_, base::Passed(&events)));
khushalsagar0a226af2015-12-09 10:30:20388}
389
390bool ProxyImpl::IsInsideDraw() {
391 return inside_draw_;
392}
393
394void ProxyImpl::RenewTreePriority() {
395 DCHECK(IsImplThread());
396 bool smoothness_takes_priority =
397 layer_tree_host_impl_->pinch_gesture_active() ||
398 layer_tree_host_impl_->page_scale_animation_active() ||
399 layer_tree_host_impl_->IsActivelyScrolling();
400
401 // Schedule expiration if smoothness currently takes priority.
402 if (smoothness_takes_priority)
403 smoothness_priority_expiration_notifier_.Schedule();
404
405 // We use the same priority for both trees by default.
406 TreePriority tree_priority = SAME_PRIORITY_FOR_BOTH_TREES;
407
408 // Smoothness takes priority if we have an expiration for it scheduled.
409 if (smoothness_priority_expiration_notifier_.HasPendingNotification())
410 tree_priority = SMOOTHNESS_TAKES_PRIORITY;
411
412 // New content always takes priority when there is an invalid viewport size or
413 // ui resources have been evicted.
414 if (layer_tree_host_impl_->active_tree()->ViewportSizeInvalid() ||
415 layer_tree_host_impl_->EvictedUIResourcesExist() ||
416 input_throttled_until_commit_) {
417 // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
418 // tree might be freed. We need to set RequiresHighResToDraw to ensure that
419 // high res tiles will be required to activate pending tree.
420 layer_tree_host_impl_->SetRequiresHighResToDraw();
421 tree_priority = NEW_CONTENT_TAKES_PRIORITY;
422 }
423
424 layer_tree_host_impl_->SetTreePriority(tree_priority);
425
426 // Only put the scheduler in impl latency prioritization mode if we don't
427 // have a scroll listener. This gives the scroll listener a better chance of
428 // handling scroll updates within the same frame. The tree itself is still
429 // kept in prefer smoothness mode to allow checkerboarding.
430 ScrollHandlerState scroll_handler_state =
431 layer_tree_host_impl_->scroll_affects_scroll_handler()
432 ? ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER
433 : ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
434 scheduler_->SetTreePrioritiesAndScrollState(tree_priority,
435 scroll_handler_state);
khushalsagar0a226af2015-12-09 10:30:20436}
437
438void ProxyImpl::PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
439 base::TimeDelta delay) {
440 DCHECK(IsImplThread());
441 task_runner_provider_->ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE,
442 task, delay);
443}
444
445void ProxyImpl::DidActivateSyncTree() {
446 TRACE_EVENT0("cc", "ProxyImpl::DidActivateSyncTreeOnImplThread");
447 DCHECK(IsImplThread());
448
sunnyps2237c9b2016-05-20 22:25:06449 if (activation_completion_event_) {
khushalsagar0a226af2015-12-09 10:30:20450 TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation",
451 TRACE_EVENT_SCOPE_THREAD);
sunnyps2237c9b2016-05-20 22:25:06452 activation_completion_event_->Signal();
453 activation_completion_event_ = nullptr;
khushalsagar0a226af2015-12-09 10:30:20454 }
khushalsagar0a226af2015-12-09 10:30:20455}
456
457void ProxyImpl::WillPrepareTiles() {
458 DCHECK(IsImplThread());
459 scheduler_->WillPrepareTiles();
460}
461
462void ProxyImpl::DidPrepareTiles() {
463 DCHECK(IsImplThread());
464 scheduler_->DidPrepareTiles();
465}
466
467void ProxyImpl::DidCompletePageScaleAnimationOnImplThread() {
468 DCHECK(IsImplThread());
khushalsagar12020cd42016-11-21 09:22:48469 MainThreadTaskRunner()->PostTask(
tzik4604bb52017-04-13 21:50:22470 FROM_HERE, base::BindOnce(&ProxyMain::DidCompletePageScaleAnimation,
471 proxy_main_weak_ptr_));
khushalsagar0a226af2015-12-09 10:30:20472}
473
danakjc7afae52017-06-20 21:12:41474void ProxyImpl::OnDrawForLayerTreeFrameSink(bool resourceless_software_draw) {
khushalsagar0a226af2015-12-09 10:30:20475 DCHECK(IsImplThread());
danakjc7afae52017-06-20 21:12:41476 scheduler_->OnDrawForLayerTreeFrameSink(resourceless_software_draw);
khushalsagar0a226af2015-12-09 10:30:20477}
478
khushalsagard3b8827d2017-02-18 18:42:54479void ProxyImpl::NeedsImplSideInvalidation() {
480 DCHECK(IsImplThread());
khushalsagar6dc91d02017-02-28 05:10:07481 scheduler_->SetNeedsImplSideInvalidation();
khushalsagard3b8827d2017-02-18 18:42:54482}
483
vmpstra840c6a2017-06-01 21:50:39484void ProxyImpl::NotifyImageDecodeRequestFinished() {
485 DCHECK(IsImplThread());
486 SetNeedsCommitOnImplThread();
487}
488
khushalsagar0a226af2015-12-09 10:30:20489void ProxyImpl::WillBeginImplFrame(const BeginFrameArgs& args) {
490 DCHECK(IsImplThread());
491 layer_tree_host_impl_->WillBeginImplFrame(args);
khushalsagar0a226af2015-12-09 10:30:20492}
493
494void ProxyImpl::DidFinishImplFrame() {
495 DCHECK(IsImplThread());
496 layer_tree_host_impl_->DidFinishImplFrame();
497}
498
eseckler9404a232017-05-22 14:49:43499void ProxyImpl::DidNotProduceFrame(const BeginFrameAck& ack) {
500 DCHECK(IsImplThread());
501 layer_tree_host_impl_->DidNotProduceFrame(ack);
502}
503
khushalsagar0a226af2015-12-09 10:30:20504void ProxyImpl::ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) {
505 DCHECK(IsImplThread());
506 unsigned int begin_frame_id = nextBeginFrameId++;
507 benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
508 benchmark_instrumentation::kSendBeginFrame, begin_frame_id);
danakj60bc3bc2016-04-09 00:24:48509 std::unique_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
khushalsagar0a226af2015-12-09 10:30:20510 new BeginMainFrameAndCommitState);
511 begin_main_frame_state->begin_frame_id = begin_frame_id;
512 begin_main_frame_state->begin_frame_args = args;
majidvp96452d02016-04-11 20:36:04513 begin_main_frame_state->begin_frame_callbacks =
514 layer_tree_host_impl_->ProcessLayerTreeMutations();
khushalsagar0a226af2015-12-09 10:30:20515 begin_main_frame_state->scroll_info =
516 layer_tree_host_impl_->ProcessScrollDeltas();
khushalsagar0a226af2015-12-09 10:30:20517 begin_main_frame_state->evicted_ui_resources =
518 layer_tree_host_impl_->EvictedUIResourcesExist();
vmpstrf386bcd2017-03-08 04:12:07519 begin_main_frame_state->completed_image_decode_callbacks =
520 layer_tree_host_impl_->TakeCompletedImageDecodeCallbacks();
khushalsagar12020cd42016-11-21 09:22:48521 MainThreadTaskRunner()->PostTask(
tzik4604bb52017-04-13 21:50:22522 FROM_HERE,
523 base::BindOnce(&ProxyMain::BeginMainFrame, proxy_main_weak_ptr_,
524 base::Passed(&begin_main_frame_state)));
khushalsagar6dc91d02017-02-28 05:10:07525 layer_tree_host_impl_->DidSendBeginMainFrame();
khushalsagar0a226af2015-12-09 10:30:20526 devtools_instrumentation::DidRequestMainThreadFrame(layer_tree_host_id_);
527}
528
danakj9d124422016-10-14 03:15:08529DrawResult ProxyImpl::ScheduledActionDrawIfPossible() {
530 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionDraw");
khushalsagar0a226af2015-12-09 10:30:20531 DCHECK(IsImplThread());
532
danakj9d124422016-10-14 03:15:08533 // The scheduler should never generate this call when it can't draw.
khushalsagar0a226af2015-12-09 10:30:20534 DCHECK(layer_tree_host_impl_->CanDraw());
535
536 bool forced_draw = false;
danakj9d124422016-10-14 03:15:08537 return DrawInternal(forced_draw);
khushalsagar0a226af2015-12-09 10:30:20538}
539
danakj9d124422016-10-14 03:15:08540DrawResult ProxyImpl::ScheduledActionDrawForced() {
541 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionDrawForced");
khushalsagar0a226af2015-12-09 10:30:20542 DCHECK(IsImplThread());
543 bool forced_draw = true;
danakj9d124422016-10-14 03:15:08544 return DrawInternal(forced_draw);
khushalsagar0a226af2015-12-09 10:30:20545}
546
547void ProxyImpl::ScheduledActionCommit() {
548 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionCommit");
549 DCHECK(IsImplThread());
550 DCHECK(IsMainThreadBlocked());
551 DCHECK(commit_completion_event_);
552
tzik3f4231f2017-03-31 21:31:24553 // Relax the cross-thread access restriction to non-thread-safe RefCount.
554 // It's safe since the main thread is blocked while a main-thread-bound
555 // compositor stuff are accessed from the impl thread.
556 base::ScopedAllowCrossThreadRefCountAccess
557 allow_cross_thread_ref_count_access;
558
khushalsagar0a226af2015-12-09 10:30:20559 layer_tree_host_impl_->BeginCommit();
560 blocked_main_commit().layer_tree_host->FinishCommitOnImplThread(
561 layer_tree_host_impl_.get());
562
563 // Remove the LayerTreeHost reference before the completion event is signaled
564 // and cleared. This is necessary since blocked_main_commit() allows access
565 // only while we have the completion event to ensure the main thread is
566 // blocked for a commit.
567 blocked_main_commit().layer_tree_host = nullptr;
568
sunnyps2237c9b2016-05-20 22:25:06569 if (commit_completion_waits_for_activation_) {
570 // For some layer types in impl-side painting, the commit is held until the
571 // sync tree is activated. It's also possible that the sync tree has
572 // already activated if there was no work to be done.
khushalsagar0a226af2015-12-09 10:30:20573 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
sunnyps2237c9b2016-05-20 22:25:06574 commit_completion_waits_for_activation_ = false;
575 activation_completion_event_ = commit_completion_event_;
khushalsagar0a226af2015-12-09 10:30:20576 } else {
577 commit_completion_event_->Signal();
khushalsagar0a226af2015-12-09 10:30:20578 }
sunnyps2237c9b2016-05-20 22:25:06579 commit_completion_event_ = nullptr;
khushalsagar0a226af2015-12-09 10:30:20580
581 scheduler_->DidCommit();
582
583 // Delay this step until afer the main thread has been released as it's
584 // often a good bit of work to update the tree and prepare the new frame.
585 layer_tree_host_impl_->CommitComplete();
586
587 SetInputThrottledUntilCommitOnImpl(false);
588
589 next_frame_is_newly_committed_frame_ = true;
590}
591
592void ProxyImpl::ScheduledActionActivateSyncTree() {
593 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionActivateSyncTree");
594 DCHECK(IsImplThread());
595 layer_tree_host_impl_->ActivateSyncTree();
596}
597
danakjc7afae52017-06-20 21:12:41598void ProxyImpl::ScheduledActionBeginLayerTreeFrameSinkCreation() {
danakj1120f4c2016-09-15 02:05:32599 TRACE_EVENT0("cc",
danakjc7afae52017-06-20 21:12:41600 "ProxyImpl::ScheduledActionBeginLayerTreeFrameSinkCreation");
khushalsagar0a226af2015-12-09 10:30:20601 DCHECK(IsImplThread());
khushalsagar12020cd42016-11-21 09:22:48602 MainThreadTaskRunner()->PostTask(
danakjc7afae52017-06-20 21:12:41603 FROM_HERE, base::BindOnce(&ProxyMain::RequestNewLayerTreeFrameSink,
tzik4604bb52017-04-13 21:50:22604 proxy_main_weak_ptr_));
khushalsagar0a226af2015-12-09 10:30:20605}
606
607void ProxyImpl::ScheduledActionPrepareTiles() {
608 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionPrepareTiles");
609 DCHECK(IsImplThread());
610 layer_tree_host_impl_->PrepareTiles();
611}
612
danakjc7afae52017-06-20 21:12:41613void ProxyImpl::ScheduledActionInvalidateLayerTreeFrameSink() {
614 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionInvalidateLayerTreeFrameSink");
khushalsagar0a226af2015-12-09 10:30:20615 DCHECK(IsImplThread());
danakjc7afae52017-06-20 21:12:41616 DCHECK(layer_tree_host_impl_->layer_tree_frame_sink());
617 layer_tree_host_impl_->layer_tree_frame_sink()->Invalidate();
khushalsagar0a226af2015-12-09 10:30:20618}
619
khushalsagarab73d502017-02-24 02:26:46620void ProxyImpl::ScheduledActionPerformImplSideInvalidation() {
khushalsagar6dc91d02017-02-28 05:10:07621 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionPerformImplSideInvalidation");
622 DCHECK(IsImplThread());
623 layer_tree_host_impl_->InvalidateContentOnImplSide();
khushalsagarab73d502017-02-24 02:26:46624}
625
khushalsagar0a226af2015-12-09 10:30:20626void ProxyImpl::SendBeginMainFrameNotExpectedSoon() {
627 DCHECK(IsImplThread());
khushalsagar12020cd42016-11-21 09:22:48628 MainThreadTaskRunner()->PostTask(
tzik4604bb52017-04-13 21:50:22629 FROM_HERE, base::BindOnce(&ProxyMain::BeginMainFrameNotExpectedSoon,
630 proxy_main_weak_ptr_));
khushalsagar0a226af2015-12-09 10:30:20631}
632
delphick9db74aa2017-05-05 10:20:49633void ProxyImpl::ScheduledActionBeginMainFrameNotExpectedUntil(
634 base::TimeTicks time) {
635 DCHECK(IsImplThread());
636 MainThreadTaskRunner()->PostTask(
637 FROM_HERE, base::Bind(&ProxyMain::BeginMainFrameNotExpectedUntil,
638 proxy_main_weak_ptr_, time));
639}
640
danakj9d124422016-10-14 03:15:08641DrawResult ProxyImpl::DrawInternal(bool forced_draw) {
642 TRACE_EVENT_SYNTHETIC_DELAY("cc.Draw");
khushalsagar0a226af2015-12-09 10:30:20643
644 DCHECK(IsImplThread());
645 DCHECK(layer_tree_host_impl_.get());
646
647 base::AutoReset<bool> mark_inside(&inside_draw_, true);
648
649 if (layer_tree_host_impl_->pending_tree()) {
650 bool update_lcd_text = false;
651 layer_tree_host_impl_->pending_tree()->UpdateDrawProperties(
652 update_lcd_text);
653 }
654
655 // This method is called on a forced draw, regardless of whether we are able
656 // to produce a frame, as the calling site on main thread is blocked until its
657 // request completes, and we signal completion here. If CanDraw() is false, we
658 // will indicate success=false to the caller, but we must still signal
659 // completion to avoid deadlock.
660
661 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
662 // frame, so can only be used when such a frame is possible. Since
663 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
664 // CanDraw() as well.
665
666 LayerTreeHostImpl::FrameData frame;
esecklerdde665f2017-03-07 20:19:27667 frame.begin_frame_ack = scheduler_->CurrentBeginFrameAckForActiveTree();
khushalsagar0a226af2015-12-09 10:30:20668 bool draw_frame = false;
669
670 DrawResult result;
671 if (layer_tree_host_impl_->CanDraw()) {
672 result = layer_tree_host_impl_->PrepareToDraw(&frame);
673 draw_frame = forced_draw || result == DRAW_SUCCESS;
674 } else {
675 result = DRAW_ABORTED_CANT_DRAW;
676 }
677
678 if (draw_frame) {
danakjaecfcfba2016-09-07 22:33:18679 if (layer_tree_host_impl_->DrawLayers(&frame))
danakjc7afae52017-06-20 21:12:41680 // Drawing implies we submitted a frame to the LayerTreeFrameSink.
danakj9d124422016-10-14 03:15:08681 scheduler_->DidSubmitCompositorFrame();
khushalsagar0a226af2015-12-09 10:30:20682 result = DRAW_SUCCESS;
683 } else {
684 DCHECK_NE(DRAW_SUCCESS, result);
685 }
danakj097919e72016-09-07 19:50:55686
khushalsagar0a226af2015-12-09 10:30:20687 layer_tree_host_impl_->DidDrawAllLayers(frame);
688
689 bool start_ready_animations = draw_frame;
690 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
691
khushalsagar0a226af2015-12-09 10:30:20692 // Tell the main thread that the the newly-commited frame was drawn.
693 if (next_frame_is_newly_committed_frame_) {
694 next_frame_is_newly_committed_frame_ = false;
khushalsagar12020cd42016-11-21 09:22:48695 MainThreadTaskRunner()->PostTask(
tzik4604bb52017-04-13 21:50:22696 FROM_HERE, base::BindOnce(&ProxyMain::DidCommitAndDrawFrame,
697 proxy_main_weak_ptr_));
khushalsagar0a226af2015-12-09 10:30:20698 }
699
700 DCHECK_NE(INVALID_RESULT, result);
701 return result;
702}
703
704bool ProxyImpl::IsImplThread() const {
705 return task_runner_provider_->IsImplThread();
706}
707
708bool ProxyImpl::IsMainThreadBlocked() const {
709 return task_runner_provider_->IsMainThreadBlocked();
710}
711
712ProxyImpl::BlockedMainCommitOnly& ProxyImpl::blocked_main_commit() {
713 DCHECK(IsMainThreadBlocked() && commit_completion_event_);
714 return main_thread_blocked_commit_vars_unsafe_;
715}
716
khushalsagar12020cd42016-11-21 09:22:48717base::SingleThreadTaskRunner* ProxyImpl::MainThreadTaskRunner() {
718 return task_runner_provider_->MainThreadTaskRunner();
719}
720
khushalsagar0a226af2015-12-09 10:30:20721} // namespace cc