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/debug/trace_event.h"
13 #include "base/debug/trace_event_synthetic_delay.h"
14 #include "base/metrics/histogram.h"
15 #include "cc/base/swap_promise.h"
16 #include "cc/debug/benchmark_instrumentation.h"
17 #include "cc/debug/devtools_instrumentation.h"
18 #include "cc/input/input_handler.h"
19 #include "cc/output/context_provider.h"
20 #include "cc/output/output_surface.h"
21 #include "cc/quads/draw_quad.h"
22 #include "cc/resources/prioritized_resource_manager.h"
23 #include "cc/scheduler/delay_based_time_source.h"
24 #include "cc/scheduler/scheduler.h"
25 #include "cc/trees/blocking_task_runner.h"
26 #include "cc/trees/layer_tree_host.h"
27 #include "cc/trees/layer_tree_impl.h"
28 #include "ui/gfx/frame_time.h"
29
30 namespace {
31
32 // Measured in seconds.
33 const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
34
35 class SwapPromiseChecker {
36 public:
SwapPromiseChecker(cc::LayerTreeHost * layer_tree_host)37 explicit SwapPromiseChecker(cc::LayerTreeHost* layer_tree_host)
38 : layer_tree_host_(layer_tree_host) {}
39
~SwapPromiseChecker()40 ~SwapPromiseChecker() {
41 layer_tree_host_->BreakSwapPromises(cc::SwapPromise::COMMIT_FAILS);
42 }
43
44 private:
45 cc::LayerTreeHost* layer_tree_host_;
46 };
47
48 } // namespace
49
50 namespace cc {
51
52 struct ThreadProxy::CommitPendingRequest {
53 CompletionEvent completion;
54 bool commit_pending;
55 };
56
57 struct ThreadProxy::SchedulerStateRequest {
58 CompletionEvent completion;
59 scoped_ptr<base::Value> state;
60 };
61
Create(LayerTreeHost * layer_tree_host,scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)62 scoped_ptr<Proxy> ThreadProxy::Create(
63 LayerTreeHost* layer_tree_host,
64 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
65 return make_scoped_ptr(new ThreadProxy(layer_tree_host, impl_task_runner))
66 .PassAs<Proxy>();
67 }
68
ThreadProxy(LayerTreeHost * layer_tree_host,scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)69 ThreadProxy::ThreadProxy(
70 LayerTreeHost* layer_tree_host,
71 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
72 : Proxy(impl_task_runner),
73 main_thread_only_vars_unsafe_(this, layer_tree_host->id()),
74 main_thread_or_blocked_vars_unsafe_(layer_tree_host),
75 compositor_thread_vars_unsafe_(this, layer_tree_host->id()) {
76 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
77 DCHECK(IsMainThread());
78 DCHECK(this->layer_tree_host());
79 }
80
MainThreadOnly(ThreadProxy * proxy,int layer_tree_host_id)81 ThreadProxy::MainThreadOnly::MainThreadOnly(ThreadProxy* proxy,
82 int layer_tree_host_id)
83 : layer_tree_host_id(layer_tree_host_id),
84 animate_requested(false),
85 commit_requested(false),
86 commit_request_sent_to_impl_thread(false),
87 started(false),
88 manage_tiles_pending(false),
89 can_cancel_commit(true),
90 defer_commits(false),
91 weak_factory(proxy) {}
92
~MainThreadOnly()93 ThreadProxy::MainThreadOnly::~MainThreadOnly() {}
94
MainThreadOrBlockedMainThread(LayerTreeHost * host)95 ThreadProxy::MainThreadOrBlockedMainThread::MainThreadOrBlockedMainThread(
96 LayerTreeHost* host)
97 : layer_tree_host(host),
98 commit_waits_for_activation(false),
99 main_thread_inside_commit(false) {}
100
~MainThreadOrBlockedMainThread()101 ThreadProxy::MainThreadOrBlockedMainThread::~MainThreadOrBlockedMainThread() {}
102
103 PrioritizedResourceManager*
contents_texture_manager()104 ThreadProxy::MainThreadOrBlockedMainThread::contents_texture_manager() {
105 return layer_tree_host->contents_texture_manager();
106 }
107
CompositorThreadOnly(ThreadProxy * proxy,int layer_tree_host_id)108 ThreadProxy::CompositorThreadOnly::CompositorThreadOnly(ThreadProxy* proxy,
109 int layer_tree_host_id)
110 : layer_tree_host_id(layer_tree_host_id),
111 contents_texture_manager(NULL),
112 commit_completion_event(NULL),
113 completion_event_for_commit_held_on_tree_activation(NULL),
114 next_frame_is_newly_committed_frame(false),
115 inside_draw(false),
116 input_throttled_until_commit(false),
117 animations_frozen_until_next_draw(false),
118 did_commit_after_animating(false),
119 smoothness_priority_expiration_notifier(
120 proxy->ImplThreadTaskRunner(),
121 base::Bind(&ThreadProxy::RenewTreePriority, base::Unretained(proxy)),
122 base::TimeDelta::FromMilliseconds(
123 kSmoothnessTakesPriorityExpirationDelay * 1000)),
124 weak_factory(proxy) {
125 }
126
~CompositorThreadOnly()127 ThreadProxy::CompositorThreadOnly::~CompositorThreadOnly() {}
128
~ThreadProxy()129 ThreadProxy::~ThreadProxy() {
130 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
131 DCHECK(IsMainThread());
132 DCHECK(!main().started);
133 }
134
FinishAllRendering()135 void ThreadProxy::FinishAllRendering() {
136 DCHECK(Proxy::IsMainThread());
137 DCHECK(!main().defer_commits);
138
139 // Make sure all GL drawing is finished on the impl thread.
140 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
141 CompletionEvent completion;
142 Proxy::ImplThreadTaskRunner()->PostTask(
143 FROM_HERE,
144 base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread,
145 impl_thread_weak_ptr_,
146 &completion));
147 completion.Wait();
148 }
149
IsStarted() const150 bool ThreadProxy::IsStarted() const {
151 DCHECK(Proxy::IsMainThread());
152 return main().started;
153 }
154
SetLayerTreeHostClientReady()155 void ThreadProxy::SetLayerTreeHostClientReady() {
156 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReady");
157 Proxy::ImplThreadTaskRunner()->PostTask(
158 FROM_HERE,
159 base::Bind(&ThreadProxy::SetLayerTreeHostClientReadyOnImplThread,
160 impl_thread_weak_ptr_));
161 }
162
SetLayerTreeHostClientReadyOnImplThread()163 void ThreadProxy::SetLayerTreeHostClientReadyOnImplThread() {
164 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReadyOnImplThread");
165 impl().scheduler->SetCanStart();
166 }
167
SetVisible(bool visible)168 void ThreadProxy::SetVisible(bool visible) {
169 TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
170 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
171
172 CompletionEvent completion;
173 Proxy::ImplThreadTaskRunner()->PostTask(
174 FROM_HERE,
175 base::Bind(&ThreadProxy::SetVisibleOnImplThread,
176 impl_thread_weak_ptr_,
177 &completion,
178 visible));
179 completion.Wait();
180 }
181
SetVisibleOnImplThread(CompletionEvent * completion,bool visible)182 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion,
183 bool visible) {
184 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
185 impl().layer_tree_host_impl->SetVisible(visible);
186 impl().scheduler->SetVisible(visible);
187 UpdateBackgroundAnimateTicking();
188 completion->Signal();
189 }
190
UpdateBackgroundAnimateTicking()191 void ThreadProxy::UpdateBackgroundAnimateTicking() {
192 bool should_background_tick =
193 !impl().scheduler->WillDrawIfNeeded() &&
194 impl().layer_tree_host_impl->active_tree()->root_layer();
195 impl().layer_tree_host_impl->UpdateBackgroundAnimateTicking(
196 should_background_tick);
197 if (should_background_tick)
198 impl().animations_frozen_until_next_draw = false;
199 }
200
DidLoseOutputSurface()201 void ThreadProxy::DidLoseOutputSurface() {
202 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurface");
203 DCHECK(IsMainThread());
204 layer_tree_host()->DidLoseOutputSurface();
205
206 {
207 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
208
209 // Return lost resources to their owners immediately.
210 BlockingTaskRunner::CapturePostTasks blocked;
211
212 CompletionEvent completion;
213 Proxy::ImplThreadTaskRunner()->PostTask(
214 FROM_HERE,
215 base::Bind(&ThreadProxy::DeleteContentsTexturesOnImplThread,
216 impl_thread_weak_ptr_,
217 &completion));
218 completion.Wait();
219 }
220 }
221
CreateAndInitializeOutputSurface()222 void ThreadProxy::CreateAndInitializeOutputSurface() {
223 TRACE_EVENT0("cc", "ThreadProxy::DoCreateAndInitializeOutputSurface");
224 DCHECK(IsMainThread());
225
226 scoped_ptr<OutputSurface> output_surface =
227 layer_tree_host()->CreateOutputSurface();
228
229 if (output_surface) {
230 Proxy::ImplThreadTaskRunner()->PostTask(
231 FROM_HERE,
232 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread,
233 impl_thread_weak_ptr_,
234 base::Passed(&output_surface)));
235 return;
236 }
237
238 DidInitializeOutputSurface(false, RendererCapabilities());
239 }
240
DidInitializeOutputSurface(bool success,const RendererCapabilities & capabilities)241 void ThreadProxy::DidInitializeOutputSurface(
242 bool success,
243 const RendererCapabilities& capabilities) {
244 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeOutputSurface");
245 DCHECK(IsMainThread());
246 main().renderer_capabilities_main_thread_copy = capabilities;
247 layer_tree_host()->OnCreateAndInitializeOutputSurfaceAttempted(success);
248
249 if (!success) {
250 Proxy::MainThreadTaskRunner()->PostTask(
251 FROM_HERE,
252 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface,
253 main_thread_weak_ptr_));
254 }
255 }
256
SetRendererCapabilitiesMainThreadCopy(const RendererCapabilities & capabilities)257 void ThreadProxy::SetRendererCapabilitiesMainThreadCopy(
258 const RendererCapabilities& capabilities) {
259 main().renderer_capabilities_main_thread_copy = capabilities;
260 }
261
SendCommitRequestToImplThreadIfNeeded()262 void ThreadProxy::SendCommitRequestToImplThreadIfNeeded() {
263 DCHECK(IsMainThread());
264 if (main().commit_request_sent_to_impl_thread)
265 return;
266 main().commit_request_sent_to_impl_thread = true;
267 Proxy::ImplThreadTaskRunner()->PostTask(
268 FROM_HERE,
269 base::Bind(&ThreadProxy::SetNeedsCommitOnImplThread,
270 impl_thread_weak_ptr_));
271 }
272
GetRendererCapabilities() const273 const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
274 DCHECK(IsMainThread());
275 DCHECK(!layer_tree_host()->output_surface_lost());
276 return main().renderer_capabilities_main_thread_copy;
277 }
278
SetNeedsAnimate()279 void ThreadProxy::SetNeedsAnimate() {
280 DCHECK(IsMainThread());
281 if (main().animate_requested)
282 return;
283
284 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
285 main().animate_requested = true;
286 SendCommitRequestToImplThreadIfNeeded();
287 }
288
SetNeedsUpdateLayers()289 void ThreadProxy::SetNeedsUpdateLayers() {
290 DCHECK(IsMainThread());
291
292 if (main().commit_request_sent_to_impl_thread)
293 return;
294 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsUpdateLayers");
295
296 SendCommitRequestToImplThreadIfNeeded();
297 }
298
SetNeedsCommit()299 void ThreadProxy::SetNeedsCommit() {
300 DCHECK(IsMainThread());
301 // Unconditionally set here to handle SetNeedsCommit calls during a commit.
302 main().can_cancel_commit = false;
303
304 if (main().commit_requested)
305 return;
306 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
307 main().commit_requested = true;
308
309 SendCommitRequestToImplThreadIfNeeded();
310 }
311
UpdateRendererCapabilitiesOnImplThread()312 void ThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
313 DCHECK(IsImplThread());
314 Proxy::MainThreadTaskRunner()->PostTask(
315 FROM_HERE,
316 base::Bind(&ThreadProxy::SetRendererCapabilitiesMainThreadCopy,
317 main_thread_weak_ptr_,
318 impl()
319 .layer_tree_host_impl->GetRendererCapabilities()
320 .MainThreadCapabilities()));
321 }
322
DidLoseOutputSurfaceOnImplThread()323 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
324 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
325 DCHECK(IsImplThread());
326 CheckOutputSurfaceStatusOnImplThread();
327 }
328
CheckOutputSurfaceStatusOnImplThread()329 void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
330 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
331 DCHECK(IsImplThread());
332 if (!impl().layer_tree_host_impl->IsContextLost())
333 return;
334 Proxy::MainThreadTaskRunner()->PostTask(
335 FROM_HERE,
336 base::Bind(&ThreadProxy::DidLoseOutputSurface, main_thread_weak_ptr_));
337 impl().scheduler->DidLoseOutputSurface();
338 }
339
CommitVSyncParameters(base::TimeTicks timebase,base::TimeDelta interval)340 void ThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
341 base::TimeDelta interval) {
342 impl().scheduler->CommitVSyncParameters(timebase, interval);
343 }
344
SetEstimatedParentDrawTime(base::TimeDelta draw_time)345 void ThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
346 impl().scheduler->SetEstimatedParentDrawTime(draw_time);
347 }
348
SetMaxSwapsPendingOnImplThread(int max)349 void ThreadProxy::SetMaxSwapsPendingOnImplThread(int max) {
350 impl().scheduler->SetMaxSwapsPending(max);
351 }
352
DidSwapBuffersOnImplThread()353 void ThreadProxy::DidSwapBuffersOnImplThread() {
354 impl().scheduler->DidSwapBuffers();
355 }
356
DidSwapBuffersCompleteOnImplThread()357 void ThreadProxy::DidSwapBuffersCompleteOnImplThread() {
358 TRACE_EVENT0("cc", "ThreadProxy::DidSwapBuffersCompleteOnImplThread");
359 DCHECK(IsImplThread());
360 impl().scheduler->DidSwapBuffersComplete();
361 Proxy::MainThreadTaskRunner()->PostTask(
362 FROM_HERE,
363 base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
364 }
365
SetNeedsBeginFrame(bool enable)366 void ThreadProxy::SetNeedsBeginFrame(bool enable) {
367 TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginFrame", "enable", enable);
368 impl().layer_tree_host_impl->SetNeedsBeginFrame(enable);
369 UpdateBackgroundAnimateTicking();
370 }
371
BeginFrame(const BeginFrameArgs & args)372 void ThreadProxy::BeginFrame(const BeginFrameArgs& args) {
373 impl().scheduler->BeginFrame(args);
374 }
375
WillBeginImplFrame(const BeginFrameArgs & args)376 void ThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
377 impl().layer_tree_host_impl->WillBeginImplFrame(args);
378 }
379
OnCanDrawStateChanged(bool can_draw)380 void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
381 TRACE_EVENT1(
382 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
383 DCHECK(IsImplThread());
384 impl().scheduler->SetCanDraw(can_draw);
385 UpdateBackgroundAnimateTicking();
386 }
387
NotifyReadyToActivate()388 void ThreadProxy::NotifyReadyToActivate() {
389 TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate");
390 impl().scheduler->NotifyReadyToActivate();
391 }
392
SetNeedsCommitOnImplThread()393 void ThreadProxy::SetNeedsCommitOnImplThread() {
394 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
395 DCHECK(IsImplThread());
396 impl().scheduler->SetNeedsCommit();
397 }
398
PostAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector> events)399 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
400 scoped_ptr<AnimationEventsVector> events) {
401 TRACE_EVENT0("cc",
402 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
403 DCHECK(IsImplThread());
404 Proxy::MainThreadTaskRunner()->PostTask(
405 FROM_HERE,
406 base::Bind(&ThreadProxy::SetAnimationEvents,
407 main_thread_weak_ptr_,
408 base::Passed(&events)));
409 }
410
ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,int priority_cutoff)411 bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
412 int priority_cutoff) {
413 DCHECK(IsImplThread());
414
415 if (!impl().contents_texture_manager)
416 return false;
417 if (!impl().layer_tree_host_impl->resource_provider())
418 return false;
419
420 bool reduce_result =
421 impl().contents_texture_manager->ReduceMemoryOnImplThread(
422 limit_bytes,
423 priority_cutoff,
424 impl().layer_tree_host_impl->resource_provider());
425 if (!reduce_result)
426 return false;
427
428 // The texture upload queue may reference textures that were just purged,
429 // clear them from the queue.
430 if (impl().current_resource_update_controller) {
431 impl()
432 .current_resource_update_controller->DiscardUploadsToEvictedResources();
433 }
434 return true;
435 }
436
IsInsideDraw()437 bool ThreadProxy::IsInsideDraw() { return impl().inside_draw; }
438
SetNeedsRedraw(const gfx::Rect & damage_rect)439 void ThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
440 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
441 DCHECK(IsMainThread());
442 Proxy::ImplThreadTaskRunner()->PostTask(
443 FROM_HERE,
444 base::Bind(&ThreadProxy::SetNeedsRedrawRectOnImplThread,
445 impl_thread_weak_ptr_,
446 damage_rect));
447 }
448
SetNextCommitWaitsForActivation()449 void ThreadProxy::SetNextCommitWaitsForActivation() {
450 DCHECK(IsMainThread());
451 DCHECK(!blocked_main().main_thread_inside_commit);
452 blocked_main().commit_waits_for_activation = true;
453 }
454
SetDeferCommits(bool defer_commits)455 void ThreadProxy::SetDeferCommits(bool defer_commits) {
456 DCHECK(IsMainThread());
457 DCHECK_NE(main().defer_commits, defer_commits);
458 main().defer_commits = defer_commits;
459
460 if (main().defer_commits)
461 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
462 else
463 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
464
465 if (!main().defer_commits && main().pending_deferred_commit)
466 Proxy::MainThreadTaskRunner()->PostTask(
467 FROM_HERE,
468 base::Bind(&ThreadProxy::BeginMainFrame,
469 main_thread_weak_ptr_,
470 base::Passed(&main().pending_deferred_commit)));
471 }
472
CommitRequested() const473 bool ThreadProxy::CommitRequested() const {
474 DCHECK(IsMainThread());
475 return main().commit_requested;
476 }
477
BeginMainFrameRequested() const478 bool ThreadProxy::BeginMainFrameRequested() const {
479 DCHECK(IsMainThread());
480 return main().commit_request_sent_to_impl_thread;
481 }
482
SetNeedsRedrawOnImplThread()483 void ThreadProxy::SetNeedsRedrawOnImplThread() {
484 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
485 DCHECK(IsImplThread());
486 impl().scheduler->SetNeedsRedraw();
487 }
488
SetNeedsAnimateOnImplThread()489 void ThreadProxy::SetNeedsAnimateOnImplThread() {
490 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimateOnImplThread");
491 DCHECK(IsImplThread());
492 impl().scheduler->SetNeedsAnimate();
493 }
494
SetNeedsManageTilesOnImplThread()495 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
496 DCHECK(IsImplThread());
497 impl().scheduler->SetNeedsManageTiles();
498 }
499
SetNeedsRedrawRectOnImplThread(const gfx::Rect & damage_rect)500 void ThreadProxy::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) {
501 DCHECK(IsImplThread());
502 impl().layer_tree_host_impl->SetViewportDamage(damage_rect);
503 SetNeedsRedrawOnImplThread();
504 }
505
SetSwapUsedIncompleteTileOnImplThread(bool used_incomplete_tile)506 void ThreadProxy::SetSwapUsedIncompleteTileOnImplThread(
507 bool used_incomplete_tile) {
508 DCHECK(IsImplThread());
509 if (used_incomplete_tile) {
510 TRACE_EVENT_INSTANT0("cc",
511 "ThreadProxy::SetSwapUsedIncompleteTileOnImplThread",
512 TRACE_EVENT_SCOPE_THREAD);
513 }
514 impl().scheduler->SetSwapUsedIncompleteTile(used_incomplete_tile);
515 }
516
DidInitializeVisibleTileOnImplThread()517 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
518 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
519 DCHECK(IsImplThread());
520 impl().scheduler->SetNeedsRedraw();
521 }
522
MainThreadHasStoppedFlinging()523 void ThreadProxy::MainThreadHasStoppedFlinging() {
524 DCHECK(IsMainThread());
525 Proxy::ImplThreadTaskRunner()->PostTask(
526 FROM_HERE,
527 base::Bind(&ThreadProxy::MainThreadHasStoppedFlingingOnImplThread,
528 impl_thread_weak_ptr_));
529 }
530
MainThreadHasStoppedFlingingOnImplThread()531 void ThreadProxy::MainThreadHasStoppedFlingingOnImplThread() {
532 DCHECK(IsImplThread());
533 impl().layer_tree_host_impl->MainThreadHasStoppedFlinging();
534 }
535
NotifyInputThrottledUntilCommit()536 void ThreadProxy::NotifyInputThrottledUntilCommit() {
537 DCHECK(IsMainThread());
538 Proxy::ImplThreadTaskRunner()->PostTask(
539 FROM_HERE,
540 base::Bind(&ThreadProxy::SetInputThrottledUntilCommitOnImplThread,
541 impl_thread_weak_ptr_,
542 true));
543 }
544
SetInputThrottledUntilCommitOnImplThread(bool is_throttled)545 void ThreadProxy::SetInputThrottledUntilCommitOnImplThread(bool is_throttled) {
546 DCHECK(IsImplThread());
547 if (is_throttled == impl().input_throttled_until_commit)
548 return;
549 impl().input_throttled_until_commit = is_throttled;
550 RenewTreePriority();
551 }
552
layer_tree_host()553 LayerTreeHost* ThreadProxy::layer_tree_host() {
554 return blocked_main().layer_tree_host;
555 }
556
layer_tree_host() const557 const LayerTreeHost* ThreadProxy::layer_tree_host() const {
558 return blocked_main().layer_tree_host;
559 }
560
main()561 ThreadProxy::MainThreadOnly& ThreadProxy::main() {
562 DCHECK(IsMainThread());
563 return main_thread_only_vars_unsafe_;
564 }
main() const565 const ThreadProxy::MainThreadOnly& ThreadProxy::main() const {
566 DCHECK(IsMainThread());
567 return main_thread_only_vars_unsafe_;
568 }
569
blocked_main()570 ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main() {
571 DCHECK(IsMainThread() || IsMainThreadBlocked());
572 return main_thread_or_blocked_vars_unsafe_;
573 }
574
blocked_main() const575 const ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main()
576 const {
577 DCHECK(IsMainThread() || IsMainThreadBlocked());
578 return main_thread_or_blocked_vars_unsafe_;
579 }
580
impl()581 ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() {
582 DCHECK(IsImplThread());
583 return compositor_thread_vars_unsafe_;
584 }
585
impl() const586 const ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() const {
587 DCHECK(IsImplThread());
588 return compositor_thread_vars_unsafe_;
589 }
590
Start()591 void ThreadProxy::Start() {
592 DCHECK(IsMainThread());
593 DCHECK(Proxy::HasImplThread());
594
595 // Create LayerTreeHostImpl.
596 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
597 CompletionEvent completion;
598 Proxy::ImplThreadTaskRunner()->PostTask(
599 FROM_HERE,
600 base::Bind(&ThreadProxy::InitializeImplOnImplThread,
601 base::Unretained(this),
602 &completion));
603 completion.Wait();
604
605 main_thread_weak_ptr_ = main().weak_factory.GetWeakPtr();
606
607 main().started = true;
608 }
609
Stop()610 void ThreadProxy::Stop() {
611 TRACE_EVENT0("cc", "ThreadProxy::Stop");
612 DCHECK(IsMainThread());
613 DCHECK(main().started);
614
615 // Synchronously finishes pending GL operations and deletes the impl.
616 // The two steps are done as separate post tasks, so that tasks posted
617 // by the GL implementation due to the Finish can be executed by the
618 // renderer before shutting it down.
619 {
620 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
621
622 CompletionEvent completion;
623 Proxy::ImplThreadTaskRunner()->PostTask(
624 FROM_HERE,
625 base::Bind(&ThreadProxy::FinishGLOnImplThread,
626 impl_thread_weak_ptr_,
627 &completion));
628 completion.Wait();
629 }
630 {
631 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
632
633 CompletionEvent completion;
634 Proxy::ImplThreadTaskRunner()->PostTask(
635 FROM_HERE,
636 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread,
637 impl_thread_weak_ptr_,
638 &completion));
639 completion.Wait();
640 }
641
642 main().weak_factory.InvalidateWeakPtrs();
643 blocked_main().layer_tree_host = NULL;
644 main().started = false;
645 }
646
ForceSerializeOnSwapBuffers()647 void ThreadProxy::ForceSerializeOnSwapBuffers() {
648 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
649 CompletionEvent completion;
650 Proxy::ImplThreadTaskRunner()->PostTask(
651 FROM_HERE,
652 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread,
653 impl_thread_weak_ptr_,
654 &completion));
655 completion.Wait();
656 }
657
ForceSerializeOnSwapBuffersOnImplThread(CompletionEvent * completion)658 void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
659 CompletionEvent* completion) {
660 if (impl().layer_tree_host_impl->renderer())
661 impl().layer_tree_host_impl->renderer()->DoNoOp();
662 completion->Signal();
663 }
664
SetDebugState(const LayerTreeDebugState & debug_state)665 void ThreadProxy::SetDebugState(const LayerTreeDebugState& debug_state) {
666 Proxy::ImplThreadTaskRunner()->PostTask(
667 FROM_HERE,
668 base::Bind(&ThreadProxy::SetDebugStateOnImplThread,
669 impl_thread_weak_ptr_,
670 debug_state));
671 }
672
SetDebugStateOnImplThread(const LayerTreeDebugState & debug_state)673 void ThreadProxy::SetDebugStateOnImplThread(
674 const LayerTreeDebugState& debug_state) {
675 DCHECK(IsImplThread());
676 impl().scheduler->SetContinuousPainting(debug_state.continuous_painting);
677 }
678
FinishAllRenderingOnImplThread(CompletionEvent * completion)679 void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) {
680 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
681 DCHECK(IsImplThread());
682 impl().layer_tree_host_impl->FinishAllRendering();
683 completion->Signal();
684 }
685
ScheduledActionSendBeginMainFrame()686 void ThreadProxy::ScheduledActionSendBeginMainFrame() {
687 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionSendBeginMainFrame");
688 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
689 new BeginMainFrameAndCommitState);
690 begin_main_frame_state->monotonic_frame_begin_time =
691 impl().layer_tree_host_impl->CurrentFrameTimeTicks();
692 begin_main_frame_state->scroll_info =
693 impl().layer_tree_host_impl->ProcessScrollDeltas();
694
695 if (!impl().layer_tree_host_impl->settings().impl_side_painting) {
696 DCHECK_GT(impl().layer_tree_host_impl->memory_allocation_limit_bytes(), 0u);
697 }
698 begin_main_frame_state->memory_allocation_limit_bytes =
699 impl().layer_tree_host_impl->memory_allocation_limit_bytes();
700 begin_main_frame_state->memory_allocation_priority_cutoff =
701 impl().layer_tree_host_impl->memory_allocation_priority_cutoff();
702 begin_main_frame_state->evicted_ui_resources =
703 impl().layer_tree_host_impl->EvictedUIResourcesExist();
704 Proxy::MainThreadTaskRunner()->PostTask(
705 FROM_HERE,
706 base::Bind(&ThreadProxy::BeginMainFrame,
707 main_thread_weak_ptr_,
708 base::Passed(&begin_main_frame_state)));
709 devtools_instrumentation::DidRequestMainThreadFrame(
710 impl().layer_tree_host_id);
711 impl().timing_history.DidBeginMainFrame();
712 }
713
BeginMainFrame(scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state)714 void ThreadProxy::BeginMainFrame(
715 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
716 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame");
717 TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
718 DCHECK(IsMainThread());
719
720 if (main().defer_commits) {
721 main().pending_deferred_commit = begin_main_frame_state.Pass();
722 layer_tree_host()->DidDeferCommit();
723 TRACE_EVENT_INSTANT0(
724 "cc", "EarlyOut_DeferCommits", TRACE_EVENT_SCOPE_THREAD);
725 return;
726 }
727
728 // If the commit finishes, LayerTreeHost will transfer its swap promises to
729 // LayerTreeImpl. The destructor of SwapPromiseChecker checks LayerTressHost's
730 // swap promises.
731 SwapPromiseChecker swap_promise_checker(layer_tree_host());
732
733 main().commit_requested = false;
734 main().commit_request_sent_to_impl_thread = false;
735 main().animate_requested = false;
736
737 if (!layer_tree_host()->visible()) {
738 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
739 bool did_handle = false;
740 Proxy::ImplThreadTaskRunner()->PostTask(
741 FROM_HERE,
742 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
743 impl_thread_weak_ptr_,
744 did_handle));
745 return;
746 }
747
748 if (layer_tree_host()->output_surface_lost()) {
749 TRACE_EVENT_INSTANT0(
750 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
751 bool did_handle = false;
752 Proxy::ImplThreadTaskRunner()->PostTask(
753 FROM_HERE,
754 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
755 impl_thread_weak_ptr_,
756 did_handle));
757 return;
758 }
759
760 // Do not notify the impl thread of commit requests that occur during
761 // the apply/animate/layout part of the BeginMainFrameAndCommit process since
762 // those commit requests will get painted immediately. Once we have done
763 // the paint, main().commit_requested will be set to false to allow new commit
764 // requests to be scheduled.
765 // On the other hand, the animate_requested flag should remain cleared
766 // here so that any animation requests generated by the apply or animate
767 // callbacks will trigger another frame.
768 main().commit_requested = true;
769 main().commit_request_sent_to_impl_thread = true;
770
771 layer_tree_host()->ApplyScrollAndScale(*begin_main_frame_state->scroll_info);
772
773 layer_tree_host()->WillBeginMainFrame();
774
775 layer_tree_host()->UpdateClientAnimations(
776 begin_main_frame_state->monotonic_frame_begin_time);
777 layer_tree_host()->AnimateLayers(
778 begin_main_frame_state->monotonic_frame_begin_time);
779 blocked_main().last_monotonic_frame_begin_time =
780 begin_main_frame_state->monotonic_frame_begin_time;
781
782 // Unlink any backings that the impl thread has evicted, so that we know to
783 // re-paint them in UpdateLayers.
784 if (blocked_main().contents_texture_manager()) {
785 blocked_main().contents_texture_manager()->UnlinkAndClearEvictedBackings();
786
787 blocked_main().contents_texture_manager()->SetMaxMemoryLimitBytes(
788 begin_main_frame_state->memory_allocation_limit_bytes);
789 blocked_main().contents_texture_manager()->SetExternalPriorityCutoff(
790 begin_main_frame_state->memory_allocation_priority_cutoff);
791 }
792
793 // Recreate all UI resources if there were evicted UI resources when the impl
794 // thread initiated the commit.
795 if (begin_main_frame_state->evicted_ui_resources)
796 layer_tree_host()->RecreateUIResources();
797
798 layer_tree_host()->Layout();
799 TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
800
801 // Clear the commit flag after updating animations and layout here --- objects
802 // that only layout when painted will trigger another SetNeedsCommit inside
803 // UpdateLayers.
804 main().commit_requested = false;
805 main().commit_request_sent_to_impl_thread = false;
806 bool can_cancel_this_commit =
807 main().can_cancel_commit && !begin_main_frame_state->evicted_ui_resources;
808 main().can_cancel_commit = true;
809
810 scoped_ptr<ResourceUpdateQueue> queue =
811 make_scoped_ptr(new ResourceUpdateQueue);
812
813 bool updated = layer_tree_host()->UpdateLayers(queue.get());
814
815 layer_tree_host()->WillCommit();
816
817 // Before calling animate, we set main().animate_requested to false. If it is
818 // true now, it means SetNeedAnimate was called again, but during a state when
819 // main().commit_request_sent_to_impl_thread = true. We need to force that
820 // call to happen again now so that the commit request is sent to the impl
821 // thread.
822 if (main().animate_requested) {
823 // Forces SetNeedsAnimate to consider posting a commit task.
824 main().animate_requested = false;
825 SetNeedsAnimate();
826 }
827
828 if (!updated && can_cancel_this_commit) {
829 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
830 bool did_handle = true;
831 Proxy::ImplThreadTaskRunner()->PostTask(
832 FROM_HERE,
833 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
834 impl_thread_weak_ptr_,
835 did_handle));
836
837 // Although the commit is internally aborted, this is because it has been
838 // detected to be a no-op. From the perspective of an embedder, this commit
839 // went through, and input should no longer be throttled, etc.
840 layer_tree_host()->CommitComplete();
841 layer_tree_host()->DidBeginMainFrame();
842 return;
843 }
844
845 // Notify the impl thread that the main thread is ready to commit. This will
846 // begin the commit process, which is blocking from the main thread's
847 // point of view, but asynchronously performed on the impl thread,
848 // coordinated by the Scheduler.
849 {
850 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame::commit");
851
852 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
853
854 // This CapturePostTasks should be destroyed before CommitComplete() is
855 // called since that goes out to the embedder, and we want the embedder
856 // to receive its callbacks before that.
857 BlockingTaskRunner::CapturePostTasks blocked;
858
859 CompletionEvent completion;
860 Proxy::ImplThreadTaskRunner()->PostTask(
861 FROM_HERE,
862 base::Bind(&ThreadProxy::StartCommitOnImplThread,
863 impl_thread_weak_ptr_,
864 &completion,
865 queue.release()));
866 completion.Wait();
867
868 RenderingStatsInstrumentation* stats_instrumentation =
869 layer_tree_host()->rendering_stats_instrumentation();
870 BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent(
871 stats_instrumentation->main_thread_rendering_stats());
872 stats_instrumentation->AccumulateAndClearMainThreadStats();
873 }
874
875 layer_tree_host()->CommitComplete();
876 layer_tree_host()->DidBeginMainFrame();
877 }
878
StartCommitOnImplThread(CompletionEvent * completion,ResourceUpdateQueue * raw_queue)879 void ThreadProxy::StartCommitOnImplThread(CompletionEvent* completion,
880 ResourceUpdateQueue* raw_queue) {
881 TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread");
882 DCHECK(!impl().commit_completion_event);
883 DCHECK(IsImplThread() && IsMainThreadBlocked());
884 DCHECK(impl().scheduler);
885 DCHECK(impl().scheduler->CommitPending());
886
887 if (!impl().layer_tree_host_impl) {
888 TRACE_EVENT_INSTANT0(
889 "cc", "EarlyOut_NoLayerTree", TRACE_EVENT_SCOPE_THREAD);
890 completion->Signal();
891 return;
892 }
893
894 // Ideally, we should inform to impl thread when BeginMainFrame is started.
895 // But, we can avoid a PostTask in here.
896 impl().scheduler->NotifyBeginMainFrameStarted();
897
898 scoped_ptr<ResourceUpdateQueue> queue(raw_queue);
899
900 if (impl().contents_texture_manager) {
901 DCHECK_EQ(impl().contents_texture_manager,
902 blocked_main().contents_texture_manager());
903 } else {
904 // Cache this pointer that was created on the main thread side to avoid a
905 // data race between creating it and using it on the compositor thread.
906 impl().contents_texture_manager = blocked_main().contents_texture_manager();
907 }
908
909 if (impl().contents_texture_manager) {
910 if (impl().contents_texture_manager->LinkedEvictedBackingsExist()) {
911 // Clear any uploads we were making to textures linked to evicted
912 // resources
913 queue->ClearUploadsToEvictedResources();
914 // Some textures in the layer tree are invalid. Kick off another commit
915 // to fill them again.
916 SetNeedsCommitOnImplThread();
917 }
918
919 impl().contents_texture_manager->PushTexturePrioritiesToBackings();
920 }
921
922 impl().commit_completion_event = completion;
923 impl().current_resource_update_controller = ResourceUpdateController::Create(
924 this,
925 Proxy::ImplThreadTaskRunner(),
926 queue.Pass(),
927 impl().layer_tree_host_impl->resource_provider());
928 impl().current_resource_update_controller->PerformMoreUpdates(
929 impl().scheduler->AnticipatedDrawTime());
930 }
931
BeginMainFrameAbortedOnImplThread(bool did_handle)932 void ThreadProxy::BeginMainFrameAbortedOnImplThread(bool did_handle) {
933 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrameAbortedOnImplThread");
934 DCHECK(IsImplThread());
935 DCHECK(impl().scheduler);
936 DCHECK(impl().scheduler->CommitPending());
937 DCHECK(!impl().layer_tree_host_impl->pending_tree());
938
939 if (did_handle)
940 SetInputThrottledUntilCommitOnImplThread(false);
941 impl().layer_tree_host_impl->BeginMainFrameAborted(did_handle);
942 impl().scheduler->BeginMainFrameAborted(did_handle);
943 }
944
ScheduledActionAnimate()945 void ThreadProxy::ScheduledActionAnimate() {
946 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionAnimate");
947 DCHECK(IsImplThread());
948
949 if (!impl().animations_frozen_until_next_draw) {
950 impl().animation_time =
951 impl().layer_tree_host_impl->CurrentFrameTimeTicks();
952 }
953 impl().layer_tree_host_impl->Animate(impl().animation_time);
954 impl().did_commit_after_animating = false;
955 }
956
ScheduledActionCommit()957 void ThreadProxy::ScheduledActionCommit() {
958 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
959 DCHECK(IsImplThread());
960 DCHECK(IsMainThreadBlocked());
961 DCHECK(impl().commit_completion_event);
962 DCHECK(impl().current_resource_update_controller);
963
964 // Complete all remaining texture updates.
965 impl().current_resource_update_controller->Finalize();
966 impl().current_resource_update_controller.reset();
967
968 if (impl().animations_frozen_until_next_draw) {
969 impl().animation_time = std::max(
970 impl().animation_time, blocked_main().last_monotonic_frame_begin_time);
971 }
972 impl().did_commit_after_animating = true;
973
974 blocked_main().main_thread_inside_commit = true;
975 impl().layer_tree_host_impl->BeginCommit();
976 layer_tree_host()->BeginCommitOnImplThread(impl().layer_tree_host_impl.get());
977 layer_tree_host()->FinishCommitOnImplThread(
978 impl().layer_tree_host_impl.get());
979 blocked_main().main_thread_inside_commit = false;
980
981 bool hold_commit = layer_tree_host()->settings().impl_side_painting &&
982 blocked_main().commit_waits_for_activation;
983 blocked_main().commit_waits_for_activation = false;
984
985 if (hold_commit) {
986 // For some layer types in impl-side painting, the commit is held until
987 // the pending tree is activated. It's also possible that the
988 // pending tree has already activated if there was no work to be done.
989 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
990 impl().completion_event_for_commit_held_on_tree_activation =
991 impl().commit_completion_event;
992 impl().commit_completion_event = NULL;
993 } else {
994 impl().commit_completion_event->Signal();
995 impl().commit_completion_event = NULL;
996 }
997
998 // Delay this step until afer the main thread has been released as it's
999 // often a good bit of work to update the tree and prepare the new frame.
1000 impl().layer_tree_host_impl->CommitComplete();
1001
1002 SetInputThrottledUntilCommitOnImplThread(false);
1003
1004 UpdateBackgroundAnimateTicking();
1005
1006 impl().next_frame_is_newly_committed_frame = true;
1007
1008 impl().timing_history.DidCommit();
1009 }
1010
ScheduledActionUpdateVisibleTiles()1011 void ThreadProxy::ScheduledActionUpdateVisibleTiles() {
1012 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionUpdateVisibleTiles");
1013 DCHECK(IsImplThread());
1014 impl().layer_tree_host_impl->UpdateVisibleTiles();
1015 }
1016
ScheduledActionActivatePendingTree()1017 void ThreadProxy::ScheduledActionActivatePendingTree() {
1018 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTree");
1019 DCHECK(IsImplThread());
1020 impl().layer_tree_host_impl->ActivatePendingTree();
1021 }
1022
ScheduledActionBeginOutputSurfaceCreation()1023 void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
1024 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginOutputSurfaceCreation");
1025 DCHECK(IsImplThread());
1026 Proxy::MainThreadTaskRunner()->PostTask(
1027 FROM_HERE,
1028 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface,
1029 main_thread_weak_ptr_));
1030 }
1031
DrawSwapInternal(bool forced_draw)1032 DrawResult ThreadProxy::DrawSwapInternal(bool forced_draw) {
1033 TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap");
1034 DrawResult result;
1035
1036 DCHECK(IsImplThread());
1037 DCHECK(impl().layer_tree_host_impl.get());
1038
1039 impl().timing_history.DidStartDrawing();
1040 base::TimeDelta draw_duration_estimate = DrawDurationEstimate();
1041 base::AutoReset<bool> mark_inside(&impl().inside_draw, true);
1042
1043 if (impl().did_commit_after_animating) {
1044 impl().layer_tree_host_impl->Animate(impl().animation_time);
1045 impl().did_commit_after_animating = false;
1046 }
1047
1048 if (impl().layer_tree_host_impl->pending_tree())
1049 impl().layer_tree_host_impl->pending_tree()->UpdateDrawProperties();
1050
1051 // This method is called on a forced draw, regardless of whether we are able
1052 // to produce a frame, as the calling site on main thread is blocked until its
1053 // request completes, and we signal completion here. If CanDraw() is false, we
1054 // will indicate success=false to the caller, but we must still signal
1055 // completion to avoid deadlock.
1056
1057 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
1058 // frame, so can only be used when such a frame is possible. Since
1059 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
1060 // CanDraw() as well.
1061
1062 LayerTreeHostImpl::FrameData frame;
1063 bool draw_frame = false;
1064
1065 if (impl().layer_tree_host_impl->CanDraw()) {
1066 result = impl().layer_tree_host_impl->PrepareToDraw(&frame);
1067 draw_frame = forced_draw || result == DRAW_SUCCESS;
1068 } else {
1069 result = DRAW_ABORTED_CANT_DRAW;
1070 }
1071
1072 if (draw_frame) {
1073 impl().layer_tree_host_impl->DrawLayers(
1074 &frame, impl().scheduler->LastBeginImplFrameTime());
1075 result = DRAW_SUCCESS;
1076 impl().animations_frozen_until_next_draw = false;
1077 } else if (result == DRAW_ABORTED_CHECKERBOARD_ANIMATIONS &&
1078 !impl().layer_tree_host_impl->settings().impl_side_painting) {
1079 // Without impl-side painting, the animated layer that is checkerboarding
1080 // will continue to checkerboard until the next commit. If this layer
1081 // continues to move during the commit, it may continue to checkerboard
1082 // after the commit since the region rasterized during the commit will not
1083 // match the region that is currently visible; eventually this
1084 // checkerboarding will be displayed when we force a draw. To avoid this,
1085 // we freeze animations until we successfully draw.
1086 impl().animations_frozen_until_next_draw = true;
1087 } else {
1088 DCHECK_NE(DRAW_SUCCESS, result);
1089 }
1090 impl().layer_tree_host_impl->DidDrawAllLayers(frame);
1091
1092 bool start_ready_animations = draw_frame;
1093 impl().layer_tree_host_impl->UpdateAnimationState(start_ready_animations);
1094
1095 if (draw_frame) {
1096 bool did_request_swap = impl().layer_tree_host_impl->SwapBuffers(frame);
1097
1098 // We don't know if we have incomplete tiles if we didn't actually swap.
1099 if (did_request_swap) {
1100 DCHECK(!frame.has_no_damage);
1101 SetSwapUsedIncompleteTileOnImplThread(frame.contains_incomplete_tile);
1102 }
1103 }
1104
1105 // Tell the main thread that the the newly-commited frame was drawn.
1106 if (impl().next_frame_is_newly_committed_frame) {
1107 impl().next_frame_is_newly_committed_frame = false;
1108 Proxy::MainThreadTaskRunner()->PostTask(
1109 FROM_HERE,
1110 base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_));
1111 }
1112
1113 if (draw_frame)
1114 CheckOutputSurfaceStatusOnImplThread();
1115
1116 if (result == DRAW_SUCCESS) {
1117 base::TimeDelta draw_duration = impl().timing_history.DidFinishDrawing();
1118
1119 base::TimeDelta draw_duration_overestimate;
1120 base::TimeDelta draw_duration_underestimate;
1121 if (draw_duration > draw_duration_estimate)
1122 draw_duration_underestimate = draw_duration - draw_duration_estimate;
1123 else
1124 draw_duration_overestimate = draw_duration_estimate - draw_duration;
1125 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration",
1126 draw_duration,
1127 base::TimeDelta::FromMilliseconds(1),
1128 base::TimeDelta::FromMilliseconds(100),
1129 50);
1130 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate",
1131 draw_duration_underestimate,
1132 base::TimeDelta::FromMilliseconds(1),
1133 base::TimeDelta::FromMilliseconds(100),
1134 50);
1135 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate",
1136 draw_duration_overestimate,
1137 base::TimeDelta::FromMilliseconds(1),
1138 base::TimeDelta::FromMilliseconds(100),
1139 50);
1140 }
1141
1142 DCHECK_NE(INVALID_RESULT, result);
1143 return result;
1144 }
1145
ScheduledActionManageTiles()1146 void ThreadProxy::ScheduledActionManageTiles() {
1147 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionManageTiles");
1148 DCHECK(impl().layer_tree_host_impl->settings().impl_side_painting);
1149 impl().layer_tree_host_impl->ManageTiles();
1150 }
1151
ScheduledActionDrawAndSwapIfPossible()1152 DrawResult ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
1153 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
1154
1155 // SchedulerStateMachine::DidDrawIfPossibleCompleted isn't set up to
1156 // handle DRAW_ABORTED_CANT_DRAW. Moreover, the scheduler should
1157 // never generate this call when it can't draw.
1158 DCHECK(impl().layer_tree_host_impl->CanDraw());
1159
1160 bool forced_draw = false;
1161 return DrawSwapInternal(forced_draw);
1162 }
1163
ScheduledActionDrawAndSwapForced()1164 DrawResult ThreadProxy::ScheduledActionDrawAndSwapForced() {
1165 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced");
1166 bool forced_draw = true;
1167 return DrawSwapInternal(forced_draw);
1168 }
1169
DidAnticipatedDrawTimeChange(base::TimeTicks time)1170 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
1171 if (impl().current_resource_update_controller)
1172 impl().current_resource_update_controller->PerformMoreUpdates(time);
1173 }
1174
DrawDurationEstimate()1175 base::TimeDelta ThreadProxy::DrawDurationEstimate() {
1176 return impl().timing_history.DrawDurationEstimate();
1177 }
1178
BeginMainFrameToCommitDurationEstimate()1179 base::TimeDelta ThreadProxy::BeginMainFrameToCommitDurationEstimate() {
1180 return impl().timing_history.BeginMainFrameToCommitDurationEstimate();
1181 }
1182
CommitToActivateDurationEstimate()1183 base::TimeDelta ThreadProxy::CommitToActivateDurationEstimate() {
1184 return impl().timing_history.CommitToActivateDurationEstimate();
1185 }
1186
DidBeginImplFrameDeadline()1187 void ThreadProxy::DidBeginImplFrameDeadline() {
1188 impl().layer_tree_host_impl->ResetCurrentFrameTimeForNextFrame();
1189 }
1190
ReadyToFinalizeTextureUpdates()1191 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1192 DCHECK(IsImplThread());
1193 impl().scheduler->NotifyReadyToCommit();
1194 }
1195
DidCommitAndDrawFrame()1196 void ThreadProxy::DidCommitAndDrawFrame() {
1197 DCHECK(IsMainThread());
1198 layer_tree_host()->DidCommitAndDrawFrame();
1199 }
1200
DidCompleteSwapBuffers()1201 void ThreadProxy::DidCompleteSwapBuffers() {
1202 DCHECK(IsMainThread());
1203 layer_tree_host()->DidCompleteSwapBuffers();
1204 }
1205
SetAnimationEvents(scoped_ptr<AnimationEventsVector> events)1206 void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
1207 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1208 DCHECK(IsMainThread());
1209 layer_tree_host()->SetAnimationEvents(events.Pass());
1210 }
1211
InitializeImplOnImplThread(CompletionEvent * completion)1212 void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) {
1213 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
1214 DCHECK(IsImplThread());
1215 impl().layer_tree_host_impl =
1216 layer_tree_host()->CreateLayerTreeHostImpl(this);
1217 SchedulerSettings scheduler_settings(layer_tree_host()->settings());
1218 impl().scheduler = Scheduler::Create(this,
1219 scheduler_settings,
1220 impl().layer_tree_host_id,
1221 ImplThreadTaskRunner());
1222 impl().scheduler->SetVisible(impl().layer_tree_host_impl->visible());
1223
1224 impl_thread_weak_ptr_ = impl().weak_factory.GetWeakPtr();
1225 completion->Signal();
1226 }
1227
DeleteContentsTexturesOnImplThread(CompletionEvent * completion)1228 void ThreadProxy::DeleteContentsTexturesOnImplThread(
1229 CompletionEvent* completion) {
1230 TRACE_EVENT0("cc", "ThreadProxy::DeleteContentsTexturesOnImplThread");
1231 DCHECK(IsImplThread());
1232 DCHECK(IsMainThreadBlocked());
1233 layer_tree_host()->DeleteContentsTexturesOnImplThread(
1234 impl().layer_tree_host_impl->resource_provider());
1235 completion->Signal();
1236 }
1237
InitializeOutputSurfaceOnImplThread(scoped_ptr<OutputSurface> output_surface)1238 void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1239 scoped_ptr<OutputSurface> output_surface) {
1240 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
1241 DCHECK(IsImplThread());
1242
1243 LayerTreeHostImpl* host_impl = impl().layer_tree_host_impl.get();
1244 bool success = host_impl->InitializeRenderer(output_surface.Pass());
1245 RendererCapabilities capabilities;
1246 if (success) {
1247 capabilities =
1248 host_impl->GetRendererCapabilities().MainThreadCapabilities();
1249 }
1250
1251 Proxy::MainThreadTaskRunner()->PostTask(
1252 FROM_HERE,
1253 base::Bind(&ThreadProxy::DidInitializeOutputSurface,
1254 main_thread_weak_ptr_,
1255 success,
1256 capabilities));
1257
1258 if (success)
1259 impl().scheduler->DidCreateAndInitializeOutputSurface();
1260 }
1261
FinishGLOnImplThread(CompletionEvent * completion)1262 void ThreadProxy::FinishGLOnImplThread(CompletionEvent* completion) {
1263 TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
1264 DCHECK(IsImplThread());
1265 if (impl().layer_tree_host_impl->resource_provider())
1266 impl().layer_tree_host_impl->resource_provider()->Finish();
1267 completion->Signal();
1268 }
1269
LayerTreeHostClosedOnImplThread(CompletionEvent * completion)1270 void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) {
1271 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1272 DCHECK(IsImplThread());
1273 DCHECK(IsMainThreadBlocked());
1274 layer_tree_host()->DeleteContentsTexturesOnImplThread(
1275 impl().layer_tree_host_impl->resource_provider());
1276 impl().current_resource_update_controller.reset();
1277 impl().layer_tree_host_impl->SetNeedsBeginFrame(false);
1278 impl().scheduler.reset();
1279 impl().layer_tree_host_impl.reset();
1280 impl().weak_factory.InvalidateWeakPtrs();
1281 impl().contents_texture_manager = NULL;
1282 completion->Signal();
1283 }
1284
MaxPartialTextureUpdates() const1285 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1286 return ResourceUpdateController::MaxPartialTextureUpdates();
1287 }
1288
BeginMainFrameAndCommitState()1289 ThreadProxy::BeginMainFrameAndCommitState::BeginMainFrameAndCommitState()
1290 : memory_allocation_limit_bytes(0),
1291 memory_allocation_priority_cutoff(0),
1292 evicted_ui_resources(false) {}
1293
~BeginMainFrameAndCommitState()1294 ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {}
1295
AsValue() const1296 scoped_ptr<base::Value> ThreadProxy::AsValue() const {
1297 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1298
1299 CompletionEvent completion;
1300 {
1301 DebugScopedSetMainThreadBlocked main_thread_blocked(
1302 const_cast<ThreadProxy*>(this));
1303 Proxy::ImplThreadTaskRunner()->PostTask(
1304 FROM_HERE,
1305 base::Bind(&ThreadProxy::AsValueOnImplThread,
1306 impl_thread_weak_ptr_,
1307 &completion,
1308 state.get()));
1309 completion.Wait();
1310 }
1311 return state.PassAs<base::Value>();
1312 }
1313
AsValueOnImplThread(CompletionEvent * completion,base::DictionaryValue * state) const1314 void ThreadProxy::AsValueOnImplThread(CompletionEvent* completion,
1315 base::DictionaryValue* state) const {
1316 state->Set("layer_tree_host_impl",
1317 impl().layer_tree_host_impl->AsValue().release());
1318 completion->Signal();
1319 }
1320
CommitPendingForTesting()1321 bool ThreadProxy::CommitPendingForTesting() {
1322 DCHECK(IsMainThread());
1323 CommitPendingRequest commit_pending_request;
1324 {
1325 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1326 Proxy::ImplThreadTaskRunner()->PostTask(
1327 FROM_HERE,
1328 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting,
1329 impl_thread_weak_ptr_,
1330 &commit_pending_request));
1331 commit_pending_request.completion.Wait();
1332 }
1333 return commit_pending_request.commit_pending;
1334 }
1335
CommitPendingOnImplThreadForTesting(CommitPendingRequest * request)1336 void ThreadProxy::CommitPendingOnImplThreadForTesting(
1337 CommitPendingRequest* request) {
1338 DCHECK(IsImplThread());
1339 if (impl().layer_tree_host_impl->output_surface())
1340 request->commit_pending = impl().scheduler->CommitPending();
1341 else
1342 request->commit_pending = false;
1343 request->completion.Signal();
1344 }
1345
SchedulerAsValueForTesting()1346 scoped_ptr<base::Value> ThreadProxy::SchedulerAsValueForTesting() {
1347 if (IsImplThread())
1348 return impl().scheduler->AsValue().Pass();
1349
1350 SchedulerStateRequest scheduler_state_request;
1351 {
1352 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1353 Proxy::ImplThreadTaskRunner()->PostTask(
1354 FROM_HERE,
1355 base::Bind(&ThreadProxy::SchedulerAsValueOnImplThreadForTesting,
1356 impl_thread_weak_ptr_,
1357 &scheduler_state_request));
1358 scheduler_state_request.completion.Wait();
1359 }
1360 return scheduler_state_request.state.Pass();
1361 }
1362
SchedulerAsValueOnImplThreadForTesting(SchedulerStateRequest * request)1363 void ThreadProxy::SchedulerAsValueOnImplThreadForTesting(
1364 SchedulerStateRequest* request) {
1365 DCHECK(IsImplThread());
1366 request->state = impl().scheduler->AsValue();
1367 request->completion.Signal();
1368 }
1369
RenewTreePriority()1370 void ThreadProxy::RenewTreePriority() {
1371 DCHECK(IsImplThread());
1372 bool smoothness_takes_priority =
1373 impl().layer_tree_host_impl->pinch_gesture_active() ||
1374 impl().layer_tree_host_impl->page_scale_animation_active() ||
1375 (impl().layer_tree_host_impl->IsCurrentlyScrolling() &&
1376 !impl().layer_tree_host_impl->scroll_affects_scroll_handler());
1377
1378 // Schedule expiration if smoothness currently takes priority.
1379 if (smoothness_takes_priority)
1380 impl().smoothness_priority_expiration_notifier.Schedule();
1381
1382 // We use the same priority for both trees by default.
1383 TreePriority priority = SAME_PRIORITY_FOR_BOTH_TREES;
1384
1385 // Smoothness takes priority if we have an expiration for it scheduled.
1386 if (impl().smoothness_priority_expiration_notifier.HasPendingNotification())
1387 priority = SMOOTHNESS_TAKES_PRIORITY;
1388
1389 // New content always takes priority when the active tree has
1390 // evicted resources or there is an invalid viewport size.
1391 if (impl().layer_tree_host_impl->active_tree()->ContentsTexturesPurged() ||
1392 impl().layer_tree_host_impl->active_tree()->ViewportSizeInvalid() ||
1393 impl().layer_tree_host_impl->EvictedUIResourcesExist() ||
1394 impl().input_throttled_until_commit) {
1395 // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
1396 // tree might be freed. We need to set RequiresHighResToDraw to ensure that
1397 // high res tiles will be required to activate pending tree.
1398 impl().layer_tree_host_impl->active_tree()->SetRequiresHighResToDraw();
1399 priority = NEW_CONTENT_TAKES_PRIORITY;
1400 }
1401
1402 impl().layer_tree_host_impl->SetTreePriority(priority);
1403 impl().scheduler->SetSmoothnessTakesPriority(priority ==
1404 SMOOTHNESS_TAKES_PRIORITY);
1405
1406 // Notify the the client of this compositor via the output surface.
1407 // TODO(epenner): Route this to compositor-thread instead of output-surface
1408 // after GTFO refactor of compositor-thread (http://crbug/170828).
1409 if (impl().layer_tree_host_impl->output_surface()) {
1410 impl()
1411 .layer_tree_host_impl->output_surface()
1412 ->UpdateSmoothnessTakesPriority(priority == SMOOTHNESS_TAKES_PRIORITY);
1413 }
1414 }
1415
PostDelayedScrollbarFadeOnImplThread(const base::Closure & start_fade,base::TimeDelta delay)1416 void ThreadProxy::PostDelayedScrollbarFadeOnImplThread(
1417 const base::Closure& start_fade,
1418 base::TimeDelta delay) {
1419 Proxy::ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, start_fade, delay);
1420 }
1421
DidActivatePendingTree()1422 void ThreadProxy::DidActivatePendingTree() {
1423 TRACE_EVENT0("cc", "ThreadProxy::DidActivatePendingTreeOnImplThread");
1424 DCHECK(IsImplThread());
1425 DCHECK(!impl().layer_tree_host_impl->pending_tree());
1426
1427 if (impl().completion_event_for_commit_held_on_tree_activation) {
1428 TRACE_EVENT_INSTANT0(
1429 "cc", "ReleaseCommitbyActivation", TRACE_EVENT_SCOPE_THREAD);
1430 DCHECK(impl().layer_tree_host_impl->settings().impl_side_painting);
1431 impl().completion_event_for_commit_held_on_tree_activation->Signal();
1432 impl().completion_event_for_commit_held_on_tree_activation = NULL;
1433 }
1434
1435 UpdateBackgroundAnimateTicking();
1436
1437 impl().timing_history.DidActivatePendingTree();
1438 }
1439
DidManageTiles()1440 void ThreadProxy::DidManageTiles() {
1441 DCHECK(IsImplThread());
1442 impl().scheduler->DidManageTiles();
1443 }
1444
1445 } // namespace cc
1446