Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(278)

Side by Side Diff: cc/trees/thread_proxy.cc

Issue 1417053005: cc: Split ThreadProxy into ProxyMain and ProxyImpl (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressing brianderson@'s comments, remove benchmark name change. Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/trees/thread_proxy.h ('k') | cc/trees/threaded_channel.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "cc/trees/thread_proxy.h"
6
7 #include <algorithm>
8 #include <string>
9
10 #include "base/auto_reset.h"
11 #include "base/bind.h"
12 #include "base/trace_event/trace_event.h"
13 #include "base/trace_event/trace_event_argument.h"
14 #include "base/trace_event/trace_event_synthetic_delay.h"
15 #include "cc/debug/benchmark_instrumentation.h"
16 #include "cc/debug/devtools_instrumentation.h"
17 #include "cc/input/input_handler.h"
18 #include "cc/input/top_controls_manager.h"
19 #include "cc/output/context_provider.h"
20 #include "cc/output/output_surface.h"
21 #include "cc/output/swap_promise.h"
22 #include "cc/quads/draw_quad.h"
23 #include "cc/scheduler/commit_earlyout_reason.h"
24 #include "cc/scheduler/compositor_timing_history.h"
25 #include "cc/scheduler/scheduler.h"
26 #include "cc/trees/blocking_task_runner.h"
27 #include "cc/trees/layer_tree_host.h"
28 #include "cc/trees/layer_tree_impl.h"
29 #include "cc/trees/scoped_abort_remaining_swap_promises.h"
30 #include "gpu/command_buffer/client/gles2_interface.h"
31
32 namespace cc {
33
34 namespace {
35
36 // Measured in seconds.
37 const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
38
39 unsigned int nextBeginFrameId = 0;
40
41 } // namespace
42
43 struct ThreadProxy::SchedulerStateRequest {
44 CompletionEvent completion;
45 scoped_ptr<base::Value> state;
46 };
47
48 scoped_ptr<Proxy> ThreadProxy::Create(
49 LayerTreeHost* layer_tree_host,
50 TaskRunnerProvider* task_runner_provider,
51 scoped_ptr<BeginFrameSource> external_begin_frame_source) {
52 return make_scoped_ptr(
53 new ThreadProxy(layer_tree_host, task_runner_provider,
54 std::move(external_begin_frame_source)));
55 }
56
57 ThreadProxy::ThreadProxy(
58 LayerTreeHost* layer_tree_host,
59 TaskRunnerProvider* task_runner_provider,
60 scoped_ptr<BeginFrameSource> external_begin_frame_source)
61 : task_runner_provider_(task_runner_provider),
62 main_thread_only_vars_unsafe_(this, layer_tree_host),
63 compositor_thread_vars_unsafe_(
64 this,
65 layer_tree_host->id(),
66 layer_tree_host->rendering_stats_instrumentation(),
67 std::move(external_begin_frame_source)) {
68 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
69 DCHECK(task_runner_provider_);
70 DCHECK(task_runner_provider_->IsMainThread());
71 DCHECK(this->main().layer_tree_host);
72 // TODO(khushalsagar): Move this to LayerTreeHost#InitializeThreaded once
73 // ThreadProxy is split. LayerTreeHost creates the channel and passes it to
74 // ProxyMain#SetChannel.
75 SetChannel(ThreadedChannel::Create(this, task_runner_provider_));
76 }
77
78 ThreadProxy::MainThreadOnly::MainThreadOnly(ThreadProxy* proxy,
79 LayerTreeHost* layer_tree_host)
80 : layer_tree_host_id(layer_tree_host->id()),
81 layer_tree_host(layer_tree_host),
82 max_requested_pipeline_stage(NO_PIPELINE_STAGE),
83 current_pipeline_stage(NO_PIPELINE_STAGE),
84 final_pipeline_stage(NO_PIPELINE_STAGE),
85 commit_waits_for_activation(false),
86 started(false),
87 prepare_tiles_pending(false),
88 defer_commits(false),
89 weak_factory(proxy) {}
90
91 ThreadProxy::MainThreadOnly::~MainThreadOnly() {}
92
93 ThreadProxy::BlockedMainCommitOnly::BlockedMainCommitOnly()
94 : layer_tree_host(nullptr) {}
95
96 ThreadProxy::BlockedMainCommitOnly::~BlockedMainCommitOnly() {}
97
98 ThreadProxy::CompositorThreadOnly::CompositorThreadOnly(
99 ThreadProxy* proxy,
100 int layer_tree_host_id,
101 RenderingStatsInstrumentation* rendering_stats_instrumentation,
102 scoped_ptr<BeginFrameSource> external_begin_frame_source)
103 : layer_tree_host_id(layer_tree_host_id),
104 next_commit_waits_for_activation(false),
105 commit_completion_event(nullptr),
106 next_frame_is_newly_committed_frame(false),
107 inside_draw(false),
108 input_throttled_until_commit(false),
109 smoothness_priority_expiration_notifier(
110 proxy->task_runner_provider()
111 ->ImplThreadTaskRunner(),
112 base::Bind(&ThreadProxy::RenewTreePriority, base::Unretained(proxy)),
113 base::TimeDelta::FromMilliseconds(
114 kSmoothnessTakesPriorityExpirationDelay * 1000)),
115 external_begin_frame_source(std::move(external_begin_frame_source)),
116 rendering_stats_instrumentation(rendering_stats_instrumentation),
117 weak_factory(proxy) {}
118
119 ThreadProxy::CompositorThreadOnly::~CompositorThreadOnly() {}
120
121 ThreadProxy::~ThreadProxy() {
122 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
123 DCHECK(task_runner_provider_->IsMainThread());
124 DCHECK(!main().started);
125 }
126
127 void ThreadProxy::SetChannel(scoped_ptr<ThreadedChannel> threaded_channel) {
128 threaded_channel_ = std::move(threaded_channel);
129 main().channel_main = threaded_channel_.get();
130 }
131
132 void ThreadProxy::FinishAllRendering() {
133 DCHECK(task_runner_provider_->IsMainThread());
134 DCHECK(!main().defer_commits);
135
136 // Make sure all GL drawing is finished on the impl thread.
137 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
138 CompletionEvent completion;
139 main().channel_main->FinishAllRenderingOnImpl(&completion);
140 completion.Wait();
141 }
142
143 bool ThreadProxy::IsStarted() const {
144 DCHECK(task_runner_provider_->IsMainThread());
145 return main().started;
146 }
147
148 bool ThreadProxy::CommitToActiveTree() const {
149 // With ThreadProxy, we use a pending tree and activate it once it's ready to
150 // draw to allow input to modify the active tree and draw during raster.
151 return false;
152 }
153
154 void ThreadProxy::SetVisible(bool visible) {
155 TRACE_EVENT1("cc", "ThreadProxy::SetVisible", "visible", visible);
156 main().channel_main->SetVisibleOnImpl(visible);
157 }
158
159 void ThreadProxy::SetVisibleOnImpl(bool visible) {
160 TRACE_EVENT1("cc", "ThreadProxy::SetVisibleOnImplThread", "visible", visible);
161 impl().layer_tree_host_impl->SetVisible(visible);
162 impl().scheduler->SetVisible(visible);
163 }
164
165 void ThreadProxy::SetThrottleFrameProduction(bool throttle) {
166 TRACE_EVENT1("cc", "ThreadProxy::SetThrottleFrameProduction", "throttle",
167 throttle);
168 main().channel_main->SetThrottleFrameProductionOnImpl(throttle);
169 }
170
171 void ThreadProxy::SetThrottleFrameProductionOnImpl(bool throttle) {
172 TRACE_EVENT1("cc", "ThreadProxy::SetThrottleFrameProductionOnImplThread",
173 "throttle", throttle);
174 impl().scheduler->SetThrottleFrameProduction(throttle);
175 }
176
177 void ThreadProxy::DidLoseOutputSurface() {
178 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurface");
179 DCHECK(task_runner_provider_->IsMainThread());
180 main().layer_tree_host->DidLoseOutputSurface();
181 }
182
183 void ThreadProxy::RequestNewOutputSurface() {
184 DCHECK(task_runner_provider_->IsMainThread());
185 main().layer_tree_host->RequestNewOutputSurface();
186 }
187
188 void ThreadProxy::SetOutputSurface(OutputSurface* output_surface) {
189 main().channel_main->InitializeOutputSurfaceOnImpl(output_surface);
190 }
191
192 void ThreadProxy::ReleaseOutputSurface() {
193 DCHECK(task_runner_provider_->IsMainThread());
194 DCHECK(main().layer_tree_host->output_surface_lost());
195
196 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
197 CompletionEvent completion;
198 main().channel_main->ReleaseOutputSurfaceOnImpl(&completion);
199 completion.Wait();
200 }
201
202 void ThreadProxy::DidInitializeOutputSurface(
203 bool success,
204 const RendererCapabilities& capabilities) {
205 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeOutputSurface");
206 DCHECK(task_runner_provider_->IsMainThread());
207
208 if (!success) {
209 main().layer_tree_host->DidFailToInitializeOutputSurface();
210 return;
211 }
212 main().renderer_capabilities_main_thread_copy = capabilities;
213 main().layer_tree_host->DidInitializeOutputSurface();
214 }
215
216 void ThreadProxy::SetRendererCapabilitiesMainCopy(
217 const RendererCapabilities& capabilities) {
218 main().renderer_capabilities_main_thread_copy = capabilities;
219 }
220
221 bool ThreadProxy::SendCommitRequestToImplThreadIfNeeded(
222 CommitPipelineStage required_stage) {
223 DCHECK(task_runner_provider_->IsMainThread());
224 DCHECK_NE(NO_PIPELINE_STAGE, required_stage);
225 bool already_posted =
226 main().max_requested_pipeline_stage != NO_PIPELINE_STAGE;
227 main().max_requested_pipeline_stage =
228 std::max(main().max_requested_pipeline_stage, required_stage);
229 if (already_posted)
230 return false;
231 main().channel_main->SetNeedsCommitOnImpl();
232 return true;
233 }
234
235 void ThreadProxy::SetNeedsCommitOnImpl() {
236 SetNeedsCommitOnImplThread();
237 }
238
239 void ThreadProxy::DidCompletePageScaleAnimation() {
240 DCHECK(task_runner_provider_->IsMainThread());
241 main().layer_tree_host->DidCompletePageScaleAnimation();
242 }
243
244 const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
245 DCHECK(task_runner_provider_->IsMainThread());
246 DCHECK(!main().layer_tree_host->output_surface_lost());
247 return main().renderer_capabilities_main_thread_copy;
248 }
249
250 void ThreadProxy::SetNeedsAnimate() {
251 DCHECK(task_runner_provider_->IsMainThread());
252 if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE)) {
253 TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsAnimate",
254 TRACE_EVENT_SCOPE_THREAD);
255 }
256 }
257
258 void ThreadProxy::SetNeedsUpdateLayers() {
259 DCHECK(task_runner_provider_->IsMainThread());
260 // If we are currently animating, make sure we also update the layers.
261 if (main().current_pipeline_stage == ANIMATE_PIPELINE_STAGE) {
262 main().final_pipeline_stage =
263 std::max(main().final_pipeline_stage, UPDATE_LAYERS_PIPELINE_STAGE);
264 return;
265 }
266 if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE)) {
267 TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsUpdateLayers",
268 TRACE_EVENT_SCOPE_THREAD);
269 }
270 }
271
272 void ThreadProxy::SetNeedsCommit() {
273 DCHECK(task_runner_provider_->IsMainThread());
274 // If we are currently animating, make sure we don't skip the commit. Note
275 // that requesting a commit during the layer update stage means we need to
276 // schedule another full commit.
277 if (main().current_pipeline_stage == ANIMATE_PIPELINE_STAGE) {
278 main().final_pipeline_stage =
279 std::max(main().final_pipeline_stage, COMMIT_PIPELINE_STAGE);
280 return;
281 }
282 if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE)) {
283 TRACE_EVENT_INSTANT0("cc", "ThreadProxy::SetNeedsCommit",
284 TRACE_EVENT_SCOPE_THREAD);
285 }
286 }
287
288 void ThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
289 DCHECK(task_runner_provider_->IsImplThread());
290 impl().channel_impl->SetRendererCapabilitiesMainCopy(
291 impl()
292 .layer_tree_host_impl->GetRendererCapabilities()
293 .MainThreadCapabilities());
294 }
295
296 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
297 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
298 DCHECK(task_runner_provider_->IsImplThread());
299 impl().channel_impl->DidLoseOutputSurface();
300 impl().scheduler->DidLoseOutputSurface();
301 }
302
303 void ThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
304 base::TimeDelta interval) {
305 impl().scheduler->CommitVSyncParameters(timebase, interval);
306 }
307
308 void ThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
309 impl().scheduler->SetEstimatedParentDrawTime(draw_time);
310 }
311
312 void ThreadProxy::DidSwapBuffersOnImplThread() {
313 impl().scheduler->DidSwapBuffers();
314 }
315
316 void ThreadProxy::DidSwapBuffersCompleteOnImplThread() {
317 TRACE_EVENT0("cc,benchmark",
318 "ThreadProxy::DidSwapBuffersCompleteOnImplThread");
319 DCHECK(task_runner_provider_->IsImplThread());
320 impl().scheduler->DidSwapBuffersComplete();
321 impl().channel_impl->DidCompleteSwapBuffers();
322 }
323
324 void ThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
325 impl().layer_tree_host_impl->WillBeginImplFrame(args);
326 if (impl().last_processed_begin_main_frame_args.IsValid()) {
327 // Last processed begin main frame args records the frame args that we sent
328 // to the main thread for the last frame that we've processed. If that is
329 // set, that means the current frame is one past the frame in which we've
330 // finished the processing.
331 impl().layer_tree_host_impl->RecordMainFrameTiming(
332 impl().last_processed_begin_main_frame_args, args);
333 impl().last_processed_begin_main_frame_args = BeginFrameArgs();
334 }
335 }
336
337 void ThreadProxy::OnResourcelessSoftareDrawStateChanged(
338 bool resourceless_draw) {
339 DCHECK(task_runner_provider_->IsImplThread());
340 impl().scheduler->SetResourcelessSoftareDraw(resourceless_draw);
341 }
342
343 void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
344 TRACE_EVENT1(
345 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
346 DCHECK(task_runner_provider_->IsImplThread());
347 impl().scheduler->SetCanDraw(can_draw);
348 }
349
350 void ThreadProxy::NotifyReadyToActivate() {
351 TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate");
352 impl().scheduler->NotifyReadyToActivate();
353 }
354
355 void ThreadProxy::NotifyReadyToDraw() {
356 TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToDraw");
357 impl().scheduler->NotifyReadyToDraw();
358 }
359
360 void ThreadProxy::SetNeedsCommitOnImplThread() {
361 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
362 DCHECK(task_runner_provider_->IsImplThread());
363 impl().scheduler->SetNeedsBeginMainFrame();
364 }
365
366 void ThreadProxy::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
367 TRACE_EVENT1("cc", "ThreadProxy::SetVideoNeedsBeginFrames",
368 "needs_begin_frames", needs_begin_frames);
369 DCHECK(task_runner_provider_->IsImplThread());
370 // In tests the layer tree is destroyed after the scheduler is.
371 if (impl().scheduler)
372 impl().scheduler->SetVideoNeedsBeginFrames(needs_begin_frames);
373 }
374
375 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
376 scoped_ptr<AnimationEventsVector> events) {
377 TRACE_EVENT0("cc",
378 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
379 DCHECK(task_runner_provider_->IsImplThread());
380 impl().channel_impl->SetAnimationEvents(std::move(events));
381 }
382
383 bool ThreadProxy::IsInsideDraw() { return impl().inside_draw; }
384
385 void ThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
386 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
387 DCHECK(task_runner_provider_->IsMainThread());
388 main().channel_main->SetNeedsRedrawOnImpl(damage_rect);
389 }
390
391 void ThreadProxy::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
392 DCHECK(task_runner_provider_->IsImplThread());
393 SetNeedsRedrawRectOnImplThread(damage_rect);
394 }
395
396 void ThreadProxy::SetNextCommitWaitsForActivation() {
397 DCHECK(task_runner_provider_->IsMainThread());
398 main().commit_waits_for_activation = true;
399 }
400
401 void ThreadProxy::SetDeferCommits(bool defer_commits) {
402 DCHECK(task_runner_provider_->IsMainThread());
403 if (main().defer_commits == defer_commits)
404 return;
405
406 main().defer_commits = defer_commits;
407 if (main().defer_commits)
408 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
409 else
410 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
411
412 main().channel_main->SetDeferCommitsOnImpl(defer_commits);
413 }
414
415 void ThreadProxy::SetDeferCommitsOnImpl(bool defer_commits) const {
416 DCHECK(task_runner_provider_->IsImplThread());
417 impl().scheduler->SetDeferCommits(defer_commits);
418 }
419
420 bool ThreadProxy::CommitRequested() const {
421 DCHECK(task_runner_provider_->IsMainThread());
422 // TODO(skyostil): Split this into something like CommitRequested() and
423 // CommitInProgress().
424 return main().current_pipeline_stage != NO_PIPELINE_STAGE ||
425 main().max_requested_pipeline_stage >= COMMIT_PIPELINE_STAGE;
426 }
427
428 bool ThreadProxy::BeginMainFrameRequested() const {
429 DCHECK(task_runner_provider_->IsMainThread());
430 return main().max_requested_pipeline_stage != NO_PIPELINE_STAGE;
431 }
432
433 void ThreadProxy::SetNeedsRedrawOnImplThread() {
434 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
435 DCHECK(task_runner_provider_->IsImplThread());
436 impl().scheduler->SetNeedsRedraw();
437 }
438
439 void ThreadProxy::SetNeedsOneBeginImplFrameOnImplThread() {
440 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsOneBeginImplFrameOnImplThread");
441 DCHECK(task_runner_provider_->IsImplThread());
442 impl().scheduler->SetNeedsOneBeginImplFrame();
443 }
444
445 void ThreadProxy::SetNeedsPrepareTilesOnImplThread() {
446 DCHECK(task_runner_provider_->IsImplThread());
447 impl().scheduler->SetNeedsPrepareTiles();
448 }
449
450 void ThreadProxy::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) {
451 DCHECK(task_runner_provider_->IsImplThread());
452 impl().layer_tree_host_impl->SetViewportDamage(damage_rect);
453 SetNeedsRedrawOnImplThread();
454 }
455
456 void ThreadProxy::MainThreadHasStoppedFlinging() {
457 DCHECK(task_runner_provider_->IsMainThread());
458 main().channel_main->MainThreadHasStoppedFlingingOnImpl();
459 }
460
461 void ThreadProxy::MainThreadHasStoppedFlingingOnImpl() {
462 DCHECK(task_runner_provider_->IsImplThread());
463 impl().layer_tree_host_impl->MainThreadHasStoppedFlinging();
464 }
465
466 void ThreadProxy::NotifyInputThrottledUntilCommit() {
467 DCHECK(task_runner_provider_->IsMainThread());
468 main().channel_main->SetInputThrottledUntilCommitOnImpl(true);
469 }
470
471 void ThreadProxy::SetInputThrottledUntilCommitOnImpl(bool is_throttled) {
472 DCHECK(task_runner_provider_->IsImplThread());
473 if (is_throttled == impl().input_throttled_until_commit)
474 return;
475 impl().input_throttled_until_commit = is_throttled;
476 RenewTreePriority();
477 }
478
479 ThreadProxy::MainThreadOnly& ThreadProxy::main() {
480 DCHECK(task_runner_provider_->IsMainThread());
481 return main_thread_only_vars_unsafe_;
482 }
483 const ThreadProxy::MainThreadOnly& ThreadProxy::main() const {
484 DCHECK(task_runner_provider_->IsMainThread());
485 return main_thread_only_vars_unsafe_;
486 }
487
488 ThreadProxy::BlockedMainCommitOnly& ThreadProxy::blocked_main_commit() {
489 DCHECK(impl().commit_completion_event);
490 DCHECK(task_runner_provider_->IsMainThreadBlocked());
491 return main_thread_blocked_commit_vars_unsafe_;
492 }
493
494 ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() {
495 DCHECK(task_runner_provider_->IsImplThread());
496 return compositor_thread_vars_unsafe_;
497 }
498
499 const ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() const {
500 DCHECK(task_runner_provider_->IsImplThread());
501 return compositor_thread_vars_unsafe_;
502 }
503
504 void ThreadProxy::Start() {
505 DCHECK(task_runner_provider_->IsMainThread());
506 DCHECK(task_runner_provider_->HasImplThread());
507
508 // Create LayerTreeHostImpl.
509 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
510 CompletionEvent completion;
511 main().channel_main->InitializeImplOnImpl(&completion,
512 main().layer_tree_host);
513 completion.Wait();
514
515 main_thread_weak_ptr_ = main().weak_factory.GetWeakPtr();
516
517 main().started = true;
518 }
519
520 void ThreadProxy::Stop() {
521 TRACE_EVENT0("cc", "ThreadProxy::Stop");
522 DCHECK(task_runner_provider_->IsMainThread());
523 DCHECK(main().started);
524
525 // Synchronously finishes pending GL operations and deletes the impl.
526 // The two steps are done as separate post tasks, so that tasks posted
527 // by the GL implementation due to the Finish can be executed by the
528 // renderer before shutting it down.
529 {
530 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
531 CompletionEvent completion;
532 main().channel_main->FinishGLOnImpl(&completion);
533 completion.Wait();
534 }
535 {
536 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
537
538 CompletionEvent completion;
539 main().channel_main->LayerTreeHostClosedOnImpl(&completion);
540 completion.Wait();
541 }
542
543 main().weak_factory.InvalidateWeakPtrs();
544 main().layer_tree_host = nullptr;
545 main().started = false;
546 }
547
548 bool ThreadProxy::SupportsImplScrolling() const {
549 return true;
550 }
551
552 void ThreadProxy::FinishAllRenderingOnImpl(CompletionEvent* completion) {
553 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
554 DCHECK(task_runner_provider_->IsImplThread());
555 impl().layer_tree_host_impl->FinishAllRendering();
556 completion->Signal();
557 }
558
559 void ThreadProxy::ScheduledActionSendBeginMainFrame(
560 const BeginFrameArgs& args) {
561 unsigned int begin_frame_id = nextBeginFrameId++;
562 benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
563 benchmark_instrumentation::kSendBeginFrame, begin_frame_id);
564 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
565 new BeginMainFrameAndCommitState);
566 begin_main_frame_state->begin_frame_id = begin_frame_id;
567 begin_main_frame_state->begin_frame_args = args;
568 begin_main_frame_state->scroll_info =
569 impl().layer_tree_host_impl->ProcessScrollDeltas();
570 begin_main_frame_state->memory_allocation_limit_bytes =
571 impl().layer_tree_host_impl->memory_allocation_limit_bytes();
572 begin_main_frame_state->evicted_ui_resources =
573 impl().layer_tree_host_impl->EvictedUIResourcesExist();
574 // TODO(vmpstr): This needs to be fixed if
575 // main_frame_before_activation_enabled is set, since we might run this code
576 // twice before recording a duration. crbug.com/469824
577 impl().last_begin_main_frame_args = begin_main_frame_state->begin_frame_args;
578 impl().channel_impl->BeginMainFrame(std::move(begin_main_frame_state));
579 devtools_instrumentation::DidRequestMainThreadFrame(
580 impl().layer_tree_host_id);
581 }
582
583 void ThreadProxy::SendBeginMainFrameNotExpectedSoon() {
584 impl().channel_impl->BeginMainFrameNotExpectedSoon();
585 }
586
587 void ThreadProxy::BeginMainFrame(
588 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
589 benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
590 benchmark_instrumentation::kDoBeginFrame,
591 begin_main_frame_state->begin_frame_id);
592
593 base::TimeTicks begin_main_frame_start_time = base::TimeTicks::Now();
594
595 TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
596 DCHECK(task_runner_provider_->IsMainThread());
597 DCHECK_EQ(NO_PIPELINE_STAGE, main().current_pipeline_stage);
598
599 if (main().defer_commits) {
600 TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
601 TRACE_EVENT_SCOPE_THREAD);
602 main().channel_main->BeginMainFrameAbortedOnImpl(
603 CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT,
604 begin_main_frame_start_time);
605 return;
606 }
607
608 // If the commit finishes, LayerTreeHost will transfer its swap promises to
609 // LayerTreeImpl. The destructor of ScopedSwapPromiseChecker aborts the
610 // remaining swap promises.
611 ScopedAbortRemainingSwapPromises swap_promise_checker(main().layer_tree_host);
612
613 main().final_pipeline_stage = main().max_requested_pipeline_stage;
614 main().max_requested_pipeline_stage = NO_PIPELINE_STAGE;
615
616 if (!main().layer_tree_host->visible()) {
617 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
618 main().channel_main->BeginMainFrameAbortedOnImpl(
619 CommitEarlyOutReason::ABORTED_NOT_VISIBLE, begin_main_frame_start_time);
620 return;
621 }
622
623 if (main().layer_tree_host->output_surface_lost()) {
624 TRACE_EVENT_INSTANT0(
625 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
626 main().channel_main->BeginMainFrameAbortedOnImpl(
627 CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST,
628 begin_main_frame_start_time);
629 return;
630 }
631
632 main().current_pipeline_stage = ANIMATE_PIPELINE_STAGE;
633
634 main().layer_tree_host->ApplyScrollAndScale(
635 begin_main_frame_state->scroll_info.get());
636
637 main().layer_tree_host->WillBeginMainFrame();
638
639 main().layer_tree_host->BeginMainFrame(
640 begin_main_frame_state->begin_frame_args);
641 main().layer_tree_host->AnimateLayers(
642 begin_main_frame_state->begin_frame_args.frame_time);
643
644 // Recreate all UI resources if there were evicted UI resources when the impl
645 // thread initiated the commit.
646 if (begin_main_frame_state->evicted_ui_resources)
647 main().layer_tree_host->RecreateUIResources();
648
649 main().layer_tree_host->RequestMainFrameUpdate();
650 TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
651
652 bool can_cancel_this_commit =
653 main().final_pipeline_stage < COMMIT_PIPELINE_STAGE &&
654 !begin_main_frame_state->evicted_ui_resources;
655
656 main().current_pipeline_stage = UPDATE_LAYERS_PIPELINE_STAGE;
657 bool should_update_layers =
658 main().final_pipeline_stage >= UPDATE_LAYERS_PIPELINE_STAGE;
659 bool updated = should_update_layers && main().layer_tree_host->UpdateLayers();
660
661 main().layer_tree_host->WillCommit();
662 devtools_instrumentation::ScopedCommitTrace commit_task(
663 main().layer_tree_host->id());
664
665 main().current_pipeline_stage = COMMIT_PIPELINE_STAGE;
666 if (!updated && can_cancel_this_commit) {
667 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
668 main().channel_main->BeginMainFrameAbortedOnImpl(
669 CommitEarlyOutReason::FINISHED_NO_UPDATES, begin_main_frame_start_time);
670
671 // Although the commit is internally aborted, this is because it has been
672 // detected to be a no-op. From the perspective of an embedder, this commit
673 // went through, and input should no longer be throttled, etc.
674 main().current_pipeline_stage = NO_PIPELINE_STAGE;
675 main().layer_tree_host->CommitComplete();
676 main().layer_tree_host->DidBeginMainFrame();
677 main().layer_tree_host->BreakSwapPromises(SwapPromise::COMMIT_NO_UPDATE);
678 return;
679 }
680
681 // Notify the impl thread that the main thread is ready to commit. This will
682 // begin the commit process, which is blocking from the main thread's
683 // point of view, but asynchronously performed on the impl thread,
684 // coordinated by the Scheduler.
685 {
686 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame::commit");
687
688 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
689
690 // This CapturePostTasks should be destroyed before CommitComplete() is
691 // called since that goes out to the embedder, and we want the embedder
692 // to receive its callbacks before that.
693 BlockingTaskRunner::CapturePostTasks blocked(
694 task_runner_provider_->blocking_main_thread_task_runner());
695
696 CompletionEvent completion;
697 main().channel_main->StartCommitOnImpl(&completion, main().layer_tree_host,
698 begin_main_frame_start_time,
699 main().commit_waits_for_activation);
700 completion.Wait();
701 main().commit_waits_for_activation = false;
702 }
703
704 main().current_pipeline_stage = NO_PIPELINE_STAGE;
705 main().layer_tree_host->CommitComplete();
706 main().layer_tree_host->DidBeginMainFrame();
707 }
708
709 void ThreadProxy::BeginMainFrameNotExpectedSoon() {
710 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrameNotExpectedSoon");
711 DCHECK(task_runner_provider_->IsMainThread());
712 main().layer_tree_host->BeginMainFrameNotExpectedSoon();
713 }
714
715 void ThreadProxy::StartCommitOnImpl(CompletionEvent* completion,
716 LayerTreeHost* layer_tree_host,
717 base::TimeTicks main_thread_start_time,
718 bool hold_commit_for_activation) {
719 TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread");
720 DCHECK(!impl().commit_completion_event);
721 DCHECK(task_runner_provider_->IsImplThread() &&
722 task_runner_provider_->IsMainThreadBlocked());
723 DCHECK(impl().scheduler);
724 DCHECK(impl().scheduler->CommitPending());
725
726 if (hold_commit_for_activation) {
727 // This commit may be aborted. Store the value for
728 // hold_commit_for_activation so that whenever the next commit is started,
729 // the main thread will be unblocked only after pending tree activation.
730 impl().next_commit_waits_for_activation = hold_commit_for_activation;
731 }
732
733 if (!impl().layer_tree_host_impl) {
734 TRACE_EVENT_INSTANT0(
735 "cc", "EarlyOut_NoLayerTree", TRACE_EVENT_SCOPE_THREAD);
736 completion->Signal();
737 return;
738 }
739
740 // Ideally, we should inform to impl thread when BeginMainFrame is started.
741 // But, we can avoid a PostTask in here.
742 impl().scheduler->NotifyBeginMainFrameStarted(main_thread_start_time);
743 impl().commit_completion_event = completion;
744 DCHECK(!blocked_main_commit().layer_tree_host);
745 blocked_main_commit().layer_tree_host = layer_tree_host;
746 impl().scheduler->NotifyReadyToCommit();
747 }
748
749 void ThreadProxy::BeginMainFrameAbortedOnImpl(
750 CommitEarlyOutReason reason,
751 base::TimeTicks main_thread_start_time) {
752 TRACE_EVENT1("cc", "ThreadProxy::BeginMainFrameAbortedOnImplThread", "reason",
753 CommitEarlyOutReasonToString(reason));
754 DCHECK(task_runner_provider_->IsImplThread());
755 DCHECK(impl().scheduler);
756 DCHECK(impl().scheduler->CommitPending());
757 DCHECK(!impl().layer_tree_host_impl->pending_tree());
758
759 if (CommitEarlyOutHandledCommit(reason)) {
760 SetInputThrottledUntilCommitOnImpl(false);
761 impl().last_processed_begin_main_frame_args =
762 impl().last_begin_main_frame_args;
763 }
764 impl().layer_tree_host_impl->BeginMainFrameAborted(reason);
765 impl().scheduler->NotifyBeginMainFrameStarted(main_thread_start_time);
766 impl().scheduler->BeginMainFrameAborted(reason);
767 }
768
769 void ThreadProxy::ScheduledActionCommit() {
770 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
771 DCHECK(task_runner_provider_->IsImplThread());
772 DCHECK(task_runner_provider_->IsMainThreadBlocked());
773 DCHECK(impl().commit_completion_event);
774 DCHECK(blocked_main_commit().layer_tree_host);
775
776 impl().layer_tree_host_impl->BeginCommit();
777 blocked_main_commit().layer_tree_host->FinishCommitOnImplThread(
778 impl().layer_tree_host_impl.get());
779
780 // Remove the LayerTreeHost reference before the completion event is signaled
781 // and cleared. This is necessary since blocked_main_commit() allows access
782 // only while we have the completion event to ensure the main thread is
783 // blocked for a commit.
784 blocked_main_commit().layer_tree_host = nullptr;
785
786 if (impl().next_commit_waits_for_activation) {
787 // For some layer types in impl-side painting, the commit is held until
788 // the sync tree is activated. It's also possible that the
789 // sync tree has already activated if there was no work to be done.
790 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
791 } else {
792 impl().commit_completion_event->Signal();
793 impl().commit_completion_event = nullptr;
794 }
795
796 impl().scheduler->DidCommit();
797
798 // Delay this step until afer the main thread has been released as it's
799 // often a good bit of work to update the tree and prepare the new frame.
800 impl().layer_tree_host_impl->CommitComplete();
801
802 SetInputThrottledUntilCommitOnImpl(false);
803
804 impl().next_frame_is_newly_committed_frame = true;
805 }
806
807 void ThreadProxy::ScheduledActionActivateSyncTree() {
808 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivateSyncTree");
809 DCHECK(task_runner_provider_->IsImplThread());
810 impl().layer_tree_host_impl->ActivateSyncTree();
811 }
812
813 void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
814 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginOutputSurfaceCreation");
815 DCHECK(task_runner_provider_->IsImplThread());
816 impl().channel_impl->RequestNewOutputSurface();
817 }
818
819 DrawResult ThreadProxy::DrawSwapInternal(bool forced_draw) {
820 TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap");
821 DrawResult result;
822
823 DCHECK(task_runner_provider_->IsImplThread());
824 DCHECK(impl().layer_tree_host_impl.get());
825
826 base::AutoReset<bool> mark_inside(&impl().inside_draw, true);
827
828 if (impl().layer_tree_host_impl->pending_tree()) {
829 bool update_lcd_text = false;
830 impl().layer_tree_host_impl->pending_tree()->UpdateDrawProperties(
831 update_lcd_text);
832 }
833
834 // This method is called on a forced draw, regardless of whether we are able
835 // to produce a frame, as the calling site on main thread is blocked until its
836 // request completes, and we signal completion here. If CanDraw() is false, we
837 // will indicate success=false to the caller, but we must still signal
838 // completion to avoid deadlock.
839
840 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
841 // frame, so can only be used when such a frame is possible. Since
842 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
843 // CanDraw() as well.
844
845 LayerTreeHostImpl::FrameData frame;
846 bool draw_frame = false;
847
848 if (impl().layer_tree_host_impl->CanDraw()) {
849 result = impl().layer_tree_host_impl->PrepareToDraw(&frame);
850 draw_frame = forced_draw || result == DRAW_SUCCESS;
851 } else {
852 result = DRAW_ABORTED_CANT_DRAW;
853 }
854
855 if (draw_frame) {
856 impl().layer_tree_host_impl->DrawLayers(&frame);
857 result = DRAW_SUCCESS;
858 } else {
859 DCHECK_NE(DRAW_SUCCESS, result);
860 }
861 impl().layer_tree_host_impl->DidDrawAllLayers(frame);
862
863 bool start_ready_animations = draw_frame;
864 impl().layer_tree_host_impl->UpdateAnimationState(start_ready_animations);
865
866 if (draw_frame)
867 impl().layer_tree_host_impl->SwapBuffers(frame);
868
869 // Tell the main thread that the the newly-commited frame was drawn.
870 if (impl().next_frame_is_newly_committed_frame) {
871 impl().next_frame_is_newly_committed_frame = false;
872 impl().channel_impl->DidCommitAndDrawFrame();
873 }
874
875 DCHECK_NE(INVALID_RESULT, result);
876 return result;
877 }
878
879 void ThreadProxy::ScheduledActionPrepareTiles() {
880 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionPrepareTiles");
881 impl().layer_tree_host_impl->PrepareTiles();
882 }
883
884 DrawResult ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
885 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
886
887 // SchedulerStateMachine::DidDrawIfPossibleCompleted isn't set up to
888 // handle DRAW_ABORTED_CANT_DRAW. Moreover, the scheduler should
889 // never generate this call when it can't draw.
890 DCHECK(impl().layer_tree_host_impl->CanDraw());
891
892 bool forced_draw = false;
893 return DrawSwapInternal(forced_draw);
894 }
895
896 DrawResult ThreadProxy::ScheduledActionDrawAndSwapForced() {
897 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced");
898 bool forced_draw = true;
899 return DrawSwapInternal(forced_draw);
900 }
901
902 void ThreadProxy::ScheduledActionInvalidateOutputSurface() {
903 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionInvalidateOutputSurface");
904 DCHECK(impl().layer_tree_host_impl->output_surface());
905 impl().layer_tree_host_impl->output_surface()->Invalidate();
906 }
907
908 void ThreadProxy::DidFinishImplFrame() {
909 impl().layer_tree_host_impl->DidFinishImplFrame();
910 }
911
912 void ThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs& args) {
913 NOTREACHED() << "Only used by SingleThreadProxy";
914 }
915
916 void ThreadProxy::SetAuthoritativeVSyncInterval(
917 const base::TimeDelta& interval) {
918 NOTREACHED() << "Only used by SingleThreadProxy";
919 }
920
921 void ThreadProxy::DidCommitAndDrawFrame() {
922 DCHECK(task_runner_provider_->IsMainThread());
923 main().layer_tree_host->DidCommitAndDrawFrame();
924 }
925
926 void ThreadProxy::DidCompleteSwapBuffers() {
927 DCHECK(task_runner_provider_->IsMainThread());
928 main().layer_tree_host->DidCompleteSwapBuffers();
929 }
930
931 void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
932 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
933 DCHECK(task_runner_provider_->IsMainThread());
934 main().layer_tree_host->SetAnimationEvents(std::move(events));
935 }
936
937 void ThreadProxy::InitializeImplOnImpl(CompletionEvent* completion,
938 LayerTreeHost* layer_tree_host) {
939 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
940 DCHECK(task_runner_provider_->IsImplThread());
941 DCHECK(task_runner_provider_->IsMainThreadBlocked());
942 DCHECK(layer_tree_host);
943
944 // TODO(khushalsagar): ThreadedChannel will create ProxyImpl here and pass a
945 // reference to itself.
946 impl().channel_impl = threaded_channel_.get();
947
948 impl().layer_tree_host_impl = layer_tree_host->CreateLayerTreeHostImpl(this);
949
950 SchedulerSettings scheduler_settings(
951 layer_tree_host->settings().ToSchedulerSettings());
952
953 scoped_ptr<CompositorTimingHistory> compositor_timing_history(
954 new CompositorTimingHistory(CompositorTimingHistory::RENDERER_UMA,
955 impl().rendering_stats_instrumentation));
956
957 impl().scheduler =
958 Scheduler::Create(this, scheduler_settings, impl().layer_tree_host_id,
959 task_runner_provider_->ImplThreadTaskRunner(),
960 impl().external_begin_frame_source.get(),
961 std::move(compositor_timing_history));
962
963 DCHECK_EQ(impl().scheduler->visible(),
964 impl().layer_tree_host_impl->visible());
965 impl_thread_weak_ptr_ = impl().weak_factory.GetWeakPtr();
966 completion->Signal();
967 }
968
969 void ThreadProxy::InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) {
970 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
971 DCHECK(task_runner_provider_->IsImplThread());
972
973 LayerTreeHostImpl* host_impl = impl().layer_tree_host_impl.get();
974 bool success = host_impl->InitializeRenderer(output_surface);
975 RendererCapabilities capabilities;
976 if (success) {
977 capabilities =
978 host_impl->GetRendererCapabilities().MainThreadCapabilities();
979 }
980
981 impl().channel_impl->DidInitializeOutputSurface(success, capabilities);
982
983 if (success)
984 impl().scheduler->DidCreateAndInitializeOutputSurface();
985 }
986
987 void ThreadProxy::ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) {
988 DCHECK(task_runner_provider_->IsImplThread());
989
990 // Unlike DidLoseOutputSurfaceOnImplThread, we don't need to call
991 // LayerTreeHost::DidLoseOutputSurface since it already knows.
992 impl().scheduler->DidLoseOutputSurface();
993 impl().layer_tree_host_impl->ReleaseOutputSurface();
994 completion->Signal();
995 }
996
997 void ThreadProxy::FinishGLOnImpl(CompletionEvent* completion) {
998 TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
999 DCHECK(task_runner_provider_->IsImplThread());
1000 if (impl().layer_tree_host_impl->output_surface()) {
1001 ContextProvider* context_provider =
1002 impl().layer_tree_host_impl->output_surface()->context_provider();
1003 if (context_provider)
1004 context_provider->ContextGL()->Finish();
1005 }
1006 completion->Signal();
1007 }
1008
1009 void ThreadProxy::LayerTreeHostClosedOnImpl(CompletionEvent* completion) {
1010 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1011 DCHECK(task_runner_provider_->IsImplThread());
1012 DCHECK(task_runner_provider_->IsMainThreadBlocked());
1013 impl().scheduler = nullptr;
1014 impl().external_begin_frame_source = nullptr;
1015 impl().layer_tree_host_impl = nullptr;
1016 impl().weak_factory.InvalidateWeakPtrs();
1017 // We need to explicitly shutdown the notifier to destroy any weakptrs it is
1018 // holding while still on the compositor thread. This also ensures any
1019 // callbacks holding a ThreadProxy pointer are cancelled.
1020 impl().smoothness_priority_expiration_notifier.Shutdown();
1021 completion->Signal();
1022 }
1023
1024 bool ThreadProxy::MainFrameWillHappenForTesting() {
1025 DCHECK(task_runner_provider_->IsMainThread());
1026 bool main_frame_will_happen = false;
1027 {
1028 DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
1029 CompletionEvent completion;
1030 main().channel_main->MainFrameWillHappenOnImplForTesting(
1031 &completion, &main_frame_will_happen);
1032 completion.Wait();
1033 }
1034 return main_frame_will_happen;
1035 }
1036
1037 void ThreadProxy::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
1038 NOTREACHED() << "Only used by SingleThreadProxy";
1039 }
1040
1041 void ThreadProxy::MainFrameWillHappenOnImplForTesting(
1042 CompletionEvent* completion,
1043 bool* main_frame_will_happen) {
1044 DCHECK(task_runner_provider_->IsImplThread());
1045 if (impl().layer_tree_host_impl->output_surface()) {
1046 *main_frame_will_happen = impl().scheduler->MainFrameForTestingWillHappen();
1047 } else {
1048 *main_frame_will_happen = false;
1049 }
1050 completion->Signal();
1051 }
1052
1053 void ThreadProxy::RenewTreePriority() {
1054 DCHECK(task_runner_provider_->IsImplThread());
1055 bool smoothness_takes_priority =
1056 impl().layer_tree_host_impl->pinch_gesture_active() ||
1057 impl().layer_tree_host_impl->page_scale_animation_active() ||
1058 impl().layer_tree_host_impl->IsActivelyScrolling();
1059
1060 // Schedule expiration if smoothness currently takes priority.
1061 if (smoothness_takes_priority)
1062 impl().smoothness_priority_expiration_notifier.Schedule();
1063
1064 // We use the same priority for both trees by default.
1065 TreePriority tree_priority = SAME_PRIORITY_FOR_BOTH_TREES;
1066
1067 // Smoothness takes priority if we have an expiration for it scheduled.
1068 if (impl().smoothness_priority_expiration_notifier.HasPendingNotification())
1069 tree_priority = SMOOTHNESS_TAKES_PRIORITY;
1070
1071 // New content always takes priority when there is an invalid viewport size or
1072 // ui resources have been evicted.
1073 if (impl().layer_tree_host_impl->active_tree()->ViewportSizeInvalid() ||
1074 impl().layer_tree_host_impl->EvictedUIResourcesExist() ||
1075 impl().input_throttled_until_commit) {
1076 // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
1077 // tree might be freed. We need to set RequiresHighResToDraw to ensure that
1078 // high res tiles will be required to activate pending tree.
1079 impl().layer_tree_host_impl->SetRequiresHighResToDraw();
1080 tree_priority = NEW_CONTENT_TAKES_PRIORITY;
1081 }
1082
1083 impl().layer_tree_host_impl->SetTreePriority(tree_priority);
1084
1085 // Only put the scheduler in impl latency prioritization mode if we don't
1086 // have a scroll listener. This gives the scroll listener a better chance of
1087 // handling scroll updates within the same frame. The tree itself is still
1088 // kept in prefer smoothness mode to allow checkerboarding.
1089 ScrollHandlerState scroll_handler_state =
1090 impl().layer_tree_host_impl->scroll_affects_scroll_handler()
1091 ? ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER
1092 : ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
1093 impl().scheduler->SetTreePrioritiesAndScrollState(tree_priority,
1094 scroll_handler_state);
1095
1096 // Notify the the client of this compositor via the output surface.
1097 // TODO(epenner): Route this to compositor-thread instead of output-surface
1098 // after GTFO refactor of compositor-thread (http://crbug/170828).
1099 if (impl().layer_tree_host_impl->output_surface()) {
1100 impl()
1101 .layer_tree_host_impl->output_surface()
1102 ->UpdateSmoothnessTakesPriority(tree_priority ==
1103 SMOOTHNESS_TAKES_PRIORITY);
1104 }
1105 }
1106
1107 void ThreadProxy::PostDelayedAnimationTaskOnImplThread(
1108 const base::Closure& task,
1109 base::TimeDelta delay) {
1110 task_runner_provider_->ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE,
1111 task, delay);
1112 }
1113
1114 void ThreadProxy::DidActivateSyncTree() {
1115 TRACE_EVENT0("cc", "ThreadProxy::DidActivateSyncTreeOnImplThread");
1116 DCHECK(task_runner_provider_->IsImplThread());
1117
1118 if (impl().next_commit_waits_for_activation) {
1119 TRACE_EVENT_INSTANT0(
1120 "cc", "ReleaseCommitbyActivation", TRACE_EVENT_SCOPE_THREAD);
1121 DCHECK(impl().commit_completion_event);
1122 impl().commit_completion_event->Signal();
1123 impl().commit_completion_event = nullptr;
1124 impl().next_commit_waits_for_activation = false;
1125 }
1126
1127 impl().last_processed_begin_main_frame_args =
1128 impl().last_begin_main_frame_args;
1129 }
1130
1131 void ThreadProxy::WillPrepareTiles() {
1132 DCHECK(task_runner_provider_->IsImplThread());
1133 impl().scheduler->WillPrepareTiles();
1134 }
1135
1136 void ThreadProxy::DidPrepareTiles() {
1137 DCHECK(task_runner_provider_->IsImplThread());
1138 impl().scheduler->DidPrepareTiles();
1139 }
1140
1141 void ThreadProxy::DidCompletePageScaleAnimationOnImplThread() {
1142 DCHECK(task_runner_provider_->IsImplThread());
1143 impl().channel_impl->DidCompletePageScaleAnimation();
1144 }
1145
1146 void ThreadProxy::OnDrawForOutputSurface() {
1147 DCHECK(task_runner_provider_->IsImplThread());
1148 impl().scheduler->OnDrawForOutputSurface();
1149 }
1150
1151 void ThreadProxy::UpdateTopControlsState(TopControlsState constraints,
1152 TopControlsState current,
1153 bool animate) {
1154 main().channel_main->UpdateTopControlsStateOnImpl(constraints, current,
1155 animate);
1156 }
1157
1158 void ThreadProxy::UpdateTopControlsStateOnImpl(TopControlsState constraints,
1159 TopControlsState current,
1160 bool animate) {
1161 DCHECK(task_runner_provider_->IsImplThread());
1162 impl().layer_tree_host_impl->top_controls_manager()->UpdateTopControlsState(
1163 constraints, current, animate);
1164 }
1165
1166 void ThreadProxy::PostFrameTimingEventsOnImplThread(
1167 scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
1168 scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
1169 DCHECK(task_runner_provider_->IsImplThread());
1170 impl().channel_impl->PostFrameTimingEventsOnMain(
1171 std::move(composite_events), std::move(main_frame_events));
1172 }
1173
1174 void ThreadProxy::PostFrameTimingEventsOnMain(
1175 scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
1176 scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
1177 DCHECK(task_runner_provider_->IsMainThread());
1178 main().layer_tree_host->RecordFrameTimingEvents(std::move(composite_events),
1179 std::move(main_frame_events));
1180 }
1181
1182 base::WeakPtr<ProxyMain> ThreadProxy::GetMainWeakPtr() {
1183 return main_thread_weak_ptr_;
1184 }
1185
1186 base::WeakPtr<ProxyImpl> ThreadProxy::GetImplWeakPtr() {
1187 return impl_thread_weak_ptr_;
1188 }
1189
1190 } // namespace cc
OLDNEW
« no previous file with comments | « cc/trees/thread_proxy.h ('k') | cc/trees/threaded_channel.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698