OLD | NEW |
| (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/single_thread_proxy.h" | |
6 | |
7 #include "base/auto_reset.h" | |
8 #include "base/profiler/scoped_tracker.h" | |
9 #include "base/trace_event/trace_event.h" | |
10 #include "cc/debug/benchmark_instrumentation.h" | |
11 #include "cc/debug/devtools_instrumentation.h" | |
12 #include "cc/output/context_provider.h" | |
13 #include "cc/output/output_surface.h" | |
14 #include "cc/quads/draw_quad.h" | |
15 #include "cc/resources/prioritized_resource_manager.h" | |
16 #include "cc/resources/resource_update_controller.h" | |
17 #include "cc/scheduler/commit_earlyout_reason.h" | |
18 #include "cc/trees/layer_tree_host.h" | |
19 #include "cc/trees/layer_tree_host_single_thread_client.h" | |
20 #include "cc/trees/layer_tree_impl.h" | |
21 #include "cc/trees/scoped_abort_remaining_swap_promises.h" | |
22 #include "ui/gfx/frame_time.h" | |
23 | |
24 namespace cc { | |
25 | |
26 scoped_ptr<Proxy> SingleThreadProxy::Create( | |
27 LayerTreeHost* layer_tree_host, | |
28 LayerTreeHostSingleThreadClient* client, | |
29 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | |
30 scoped_ptr<BeginFrameSource> external_begin_frame_source) { | |
31 return make_scoped_ptr(new SingleThreadProxy( | |
32 layer_tree_host, | |
33 client, | |
34 main_task_runner, | |
35 external_begin_frame_source.Pass())); | |
36 } | |
37 | |
38 SingleThreadProxy::SingleThreadProxy( | |
39 LayerTreeHost* layer_tree_host, | |
40 LayerTreeHostSingleThreadClient* client, | |
41 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | |
42 scoped_ptr<BeginFrameSource> external_begin_frame_source) | |
43 : Proxy(main_task_runner, NULL), | |
44 layer_tree_host_(layer_tree_host), | |
45 client_(client), | |
46 timing_history_(layer_tree_host->rendering_stats_instrumentation()), | |
47 next_frame_is_newly_committed_frame_(false), | |
48 inside_draw_(false), | |
49 defer_commits_(false), | |
50 commit_requested_(false), | |
51 inside_synchronous_composite_(false), | |
52 output_surface_creation_requested_(false), | |
53 external_begin_frame_source_(external_begin_frame_source.Pass()), | |
54 weak_factory_(this) { | |
55 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy"); | |
56 DCHECK(Proxy::IsMainThread()); | |
57 DCHECK(layer_tree_host); | |
58 } | |
59 | |
60 void SingleThreadProxy::Start() { | |
61 DebugScopedSetImplThread impl(this); | |
62 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this); | |
63 } | |
64 | |
65 SingleThreadProxy::~SingleThreadProxy() { | |
66 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy"); | |
67 DCHECK(Proxy::IsMainThread()); | |
68 // Make sure Stop() got called or never Started. | |
69 DCHECK(!layer_tree_host_impl_); | |
70 } | |
71 | |
72 void SingleThreadProxy::FinishAllRendering() { | |
73 TRACE_EVENT0("cc", "SingleThreadProxy::FinishAllRendering"); | |
74 DCHECK(Proxy::IsMainThread()); | |
75 { | |
76 DebugScopedSetImplThread impl(this); | |
77 layer_tree_host_impl_->FinishAllRendering(); | |
78 } | |
79 } | |
80 | |
81 bool SingleThreadProxy::IsStarted() const { | |
82 DCHECK(Proxy::IsMainThread()); | |
83 return layer_tree_host_impl_; | |
84 } | |
85 | |
86 bool SingleThreadProxy::CommitToActiveTree() const { | |
87 // With SingleThreadProxy we skip the pending tree and commit directly to the | |
88 // active tree. | |
89 return true; | |
90 } | |
91 | |
92 void SingleThreadProxy::SetLayerTreeHostClientReady() { | |
93 TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady"); | |
94 // Scheduling is controlled by the embedder in the single thread case, so | |
95 // nothing to do. | |
96 DCHECK(Proxy::IsMainThread()); | |
97 DebugScopedSetImplThread impl(this); | |
98 if (layer_tree_host_->settings().single_thread_proxy_scheduler && | |
99 !scheduler_on_impl_thread_) { | |
100 SchedulerSettings scheduler_settings( | |
101 layer_tree_host_->settings().ToSchedulerSettings()); | |
102 // SingleThreadProxy should run in main thread low latency mode. | |
103 scheduler_settings.main_thread_should_always_be_low_latency = true; | |
104 scheduler_on_impl_thread_ = | |
105 Scheduler::Create(this, | |
106 scheduler_settings, | |
107 layer_tree_host_->id(), | |
108 MainThreadTaskRunner(), | |
109 external_begin_frame_source_.Pass()); | |
110 scheduler_on_impl_thread_->SetCanStart(); | |
111 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); | |
112 } | |
113 } | |
114 | |
115 void SingleThreadProxy::SetVisible(bool visible) { | |
116 TRACE_EVENT1("cc", "SingleThreadProxy::SetVisible", "visible", visible); | |
117 DebugScopedSetImplThread impl(this); | |
118 layer_tree_host_impl_->SetVisible(visible); | |
119 if (scheduler_on_impl_thread_) | |
120 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); | |
121 // Changing visibility could change ShouldComposite(). | |
122 } | |
123 | |
124 void SingleThreadProxy::SetThrottleFrameProduction(bool throttle) { | |
125 TRACE_EVENT1("cc", "SingleThreadProxy::SetThrottleFrameProduction", | |
126 "throttle", throttle); | |
127 DebugScopedSetImplThread impl(this); | |
128 if (scheduler_on_impl_thread_) | |
129 scheduler_on_impl_thread_->SetThrottleFrameProduction(throttle); | |
130 } | |
131 | |
132 void SingleThreadProxy::RequestNewOutputSurface() { | |
133 DCHECK(Proxy::IsMainThread()); | |
134 DCHECK(layer_tree_host_->output_surface_lost()); | |
135 output_surface_creation_callback_.Cancel(); | |
136 if (output_surface_creation_requested_) | |
137 return; | |
138 output_surface_creation_requested_ = true; | |
139 layer_tree_host_->RequestNewOutputSurface(); | |
140 } | |
141 | |
142 void SingleThreadProxy::SetOutputSurface( | |
143 scoped_ptr<OutputSurface> output_surface) { | |
144 DCHECK(Proxy::IsMainThread()); | |
145 DCHECK(layer_tree_host_->output_surface_lost()); | |
146 DCHECK(output_surface_creation_requested_); | |
147 renderer_capabilities_for_main_thread_ = RendererCapabilities(); | |
148 | |
149 bool success; | |
150 { | |
151 DebugScopedSetMainThreadBlocked main_thread_blocked(this); | |
152 DebugScopedSetImplThread impl(this); | |
153 layer_tree_host_->DeleteContentsTexturesOnImplThread( | |
154 layer_tree_host_impl_->resource_provider()); | |
155 success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass()); | |
156 } | |
157 | |
158 if (success) { | |
159 layer_tree_host_->DidInitializeOutputSurface(); | |
160 if (scheduler_on_impl_thread_) | |
161 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface(); | |
162 else if (!inside_synchronous_composite_) | |
163 SetNeedsCommit(); | |
164 output_surface_creation_requested_ = false; | |
165 } else { | |
166 // DidFailToInitializeOutputSurface is treated as a RequestNewOutputSurface, | |
167 // and so output_surface_creation_requested remains true. | |
168 layer_tree_host_->DidFailToInitializeOutputSurface(); | |
169 } | |
170 } | |
171 | |
172 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const { | |
173 DCHECK(Proxy::IsMainThread()); | |
174 DCHECK(!layer_tree_host_->output_surface_lost()); | |
175 return renderer_capabilities_for_main_thread_; | |
176 } | |
177 | |
178 void SingleThreadProxy::SetNeedsAnimate() { | |
179 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate"); | |
180 DCHECK(Proxy::IsMainThread()); | |
181 client_->ScheduleAnimation(); | |
182 SetNeedsCommit(); | |
183 } | |
184 | |
185 void SingleThreadProxy::SetNeedsUpdateLayers() { | |
186 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers"); | |
187 DCHECK(Proxy::IsMainThread()); | |
188 SetNeedsCommit(); | |
189 } | |
190 | |
191 void SingleThreadProxy::DoAnimate() { | |
192 // Don't animate if there is no root layer. | |
193 // TODO(mithro): Both Animate and UpdateAnimationState already have a | |
194 // "!active_tree_->root_layer()" check? | |
195 if (!layer_tree_host_impl_->active_tree()->root_layer()) { | |
196 return; | |
197 } | |
198 | |
199 layer_tree_host_impl_->Animate( | |
200 layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time); | |
201 | |
202 // If animations are not visible, update the animation state now as it | |
203 // won't happen in DoComposite. | |
204 if (!layer_tree_host_impl_->AnimationsAreVisible()) { | |
205 layer_tree_host_impl_->UpdateAnimationState(true); | |
206 } | |
207 } | |
208 | |
209 void SingleThreadProxy::DoCommit() { | |
210 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit"); | |
211 DCHECK(Proxy::IsMainThread()); | |
212 | |
213 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is | |
214 // fixed. | |
215 tracked_objects::ScopedTracker tracking_profile1( | |
216 FROM_HERE_WITH_EXPLICIT_FUNCTION("461509 SingleThreadProxy::DoCommit1")); | |
217 commit_requested_ = false; | |
218 layer_tree_host_->WillCommit(); | |
219 devtools_instrumentation::ScopedCommitTrace commit_task( | |
220 layer_tree_host_->id()); | |
221 | |
222 // Commit immediately. | |
223 { | |
224 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
225 // is fixed. | |
226 tracked_objects::ScopedTracker tracking_profile2( | |
227 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
228 "461509 SingleThreadProxy::DoCommit2")); | |
229 DebugScopedSetMainThreadBlocked main_thread_blocked(this); | |
230 DebugScopedSetImplThread impl(this); | |
231 | |
232 // This CapturePostTasks should be destroyed before CommitComplete() is | |
233 // called since that goes out to the embedder, and we want the embedder | |
234 // to receive its callbacks before that. | |
235 commit_blocking_task_runner_.reset(new BlockingTaskRunner::CapturePostTasks( | |
236 blocking_main_thread_task_runner())); | |
237 | |
238 layer_tree_host_impl_->BeginCommit(); | |
239 | |
240 if (PrioritizedResourceManager* contents_texture_manager = | |
241 layer_tree_host_->contents_texture_manager()) { | |
242 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
243 // is fixed. | |
244 tracked_objects::ScopedTracker tracking_profile3( | |
245 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
246 "461509 SingleThreadProxy::DoCommit3")); | |
247 contents_texture_manager->PushTexturePrioritiesToBackings(); | |
248 } | |
249 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get()); | |
250 | |
251 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
252 // is fixed. | |
253 tracked_objects::ScopedTracker tracking_profile4( | |
254 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
255 "461509 SingleThreadProxy::DoCommit4")); | |
256 scoped_ptr<ResourceUpdateController> update_controller = | |
257 ResourceUpdateController::Create( | |
258 NULL, | |
259 MainThreadTaskRunner(), | |
260 queue_for_commit_.Pass(), | |
261 layer_tree_host_impl_->resource_provider()); | |
262 | |
263 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
264 // is fixed. | |
265 tracked_objects::ScopedTracker tracking_profile5( | |
266 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
267 "461509 SingleThreadProxy::DoCommit5")); | |
268 update_controller->Finalize(); | |
269 | |
270 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
271 // is fixed. | |
272 tracked_objects::ScopedTracker tracking_profile6( | |
273 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
274 "461509 SingleThreadProxy::DoCommit6")); | |
275 if (layer_tree_host_impl_->EvictedUIResourcesExist()) | |
276 layer_tree_host_->RecreateUIResources(); | |
277 | |
278 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
279 // is fixed. | |
280 tracked_objects::ScopedTracker tracking_profile7( | |
281 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
282 "461509 SingleThreadProxy::DoCommit7")); | |
283 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get()); | |
284 | |
285 #if DCHECK_IS_ON() | |
286 // In the single-threaded case, the scale and scroll deltas should never be | |
287 // touched on the impl layer tree. | |
288 scoped_ptr<ScrollAndScaleSet> scroll_info = | |
289 layer_tree_host_impl_->ProcessScrollDeltas(); | |
290 DCHECK(!scroll_info->scrolls.size()); | |
291 DCHECK_EQ(1.f, scroll_info->page_scale_delta); | |
292 #endif | |
293 | |
294 if (layer_tree_host_->settings().impl_side_painting) { | |
295 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
296 // is fixed. | |
297 tracked_objects::ScopedTracker tracking_profile8( | |
298 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
299 "461509 SingleThreadProxy::DoCommit8")); | |
300 // Commit goes directly to the active tree, but we need to synchronously | |
301 // "activate" the tree still during commit to satisfy any potential | |
302 // SetNextCommitWaitsForActivation calls. Unfortunately, the tree | |
303 // might not be ready to draw, so DidActivateSyncTree must set | |
304 // the flag to force the tree to not draw until textures are ready. | |
305 NotifyReadyToActivate(); | |
306 } else { | |
307 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
308 // is fixed. | |
309 tracked_objects::ScopedTracker tracking_profile9( | |
310 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
311 "461509 SingleThreadProxy::DoCommit9")); | |
312 CommitComplete(); | |
313 } | |
314 } | |
315 } | |
316 | |
317 void SingleThreadProxy::CommitComplete() { | |
318 DCHECK(!layer_tree_host_impl_->pending_tree()) | |
319 << "Activation is expected to have synchronously occurred by now."; | |
320 DCHECK(commit_blocking_task_runner_); | |
321 | |
322 // Notify commit complete on the impl side after activate to satisfy any | |
323 // SetNextCommitWaitsForActivation calls. | |
324 layer_tree_host_impl_->CommitComplete(); | |
325 | |
326 DebugScopedSetMainThread main(this); | |
327 commit_blocking_task_runner_.reset(); | |
328 layer_tree_host_->CommitComplete(); | |
329 layer_tree_host_->DidBeginMainFrame(); | |
330 timing_history_.DidCommit(); | |
331 | |
332 next_frame_is_newly_committed_frame_ = true; | |
333 } | |
334 | |
335 void SingleThreadProxy::SetNeedsCommit() { | |
336 DCHECK(Proxy::IsMainThread()); | |
337 DebugScopedSetImplThread impl(this); | |
338 client_->ScheduleComposite(); | |
339 if (scheduler_on_impl_thread_) | |
340 scheduler_on_impl_thread_->SetNeedsCommit(); | |
341 commit_requested_ = true; | |
342 } | |
343 | |
344 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) { | |
345 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw"); | |
346 DCHECK(Proxy::IsMainThread()); | |
347 DebugScopedSetImplThread impl(this); | |
348 client_->ScheduleComposite(); | |
349 SetNeedsRedrawRectOnImplThread(damage_rect); | |
350 } | |
351 | |
352 void SingleThreadProxy::SetNextCommitWaitsForActivation() { | |
353 // Activation always forced in commit, so nothing to do. | |
354 DCHECK(Proxy::IsMainThread()); | |
355 } | |
356 | |
357 void SingleThreadProxy::SetDeferCommits(bool defer_commits) { | |
358 DCHECK(Proxy::IsMainThread()); | |
359 // Deferring commits only makes sense if there's a scheduler. | |
360 if (!scheduler_on_impl_thread_) | |
361 return; | |
362 if (defer_commits_ == defer_commits) | |
363 return; | |
364 | |
365 if (defer_commits) | |
366 TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this); | |
367 else | |
368 TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this); | |
369 | |
370 defer_commits_ = defer_commits; | |
371 scheduler_on_impl_thread_->SetDeferCommits(defer_commits); | |
372 } | |
373 | |
374 bool SingleThreadProxy::CommitRequested() const { | |
375 DCHECK(Proxy::IsMainThread()); | |
376 return commit_requested_; | |
377 } | |
378 | |
379 bool SingleThreadProxy::BeginMainFrameRequested() const { | |
380 DCHECK(Proxy::IsMainThread()); | |
381 // If there is no scheduler, then there can be no pending begin frame, | |
382 // as all frames are all manually initiated by the embedder of cc. | |
383 if (!scheduler_on_impl_thread_) | |
384 return false; | |
385 return commit_requested_; | |
386 } | |
387 | |
388 size_t SingleThreadProxy::MaxPartialTextureUpdates() const { | |
389 return std::numeric_limits<size_t>::max(); | |
390 } | |
391 | |
392 void SingleThreadProxy::Stop() { | |
393 TRACE_EVENT0("cc", "SingleThreadProxy::stop"); | |
394 DCHECK(Proxy::IsMainThread()); | |
395 { | |
396 DebugScopedSetMainThreadBlocked main_thread_blocked(this); | |
397 DebugScopedSetImplThread impl(this); | |
398 | |
399 BlockingTaskRunner::CapturePostTasks blocked( | |
400 blocking_main_thread_task_runner()); | |
401 layer_tree_host_->DeleteContentsTexturesOnImplThread( | |
402 layer_tree_host_impl_->resource_provider()); | |
403 scheduler_on_impl_thread_ = nullptr; | |
404 layer_tree_host_impl_ = nullptr; | |
405 } | |
406 layer_tree_host_ = NULL; | |
407 } | |
408 | |
409 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) { | |
410 TRACE_EVENT1( | |
411 "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw); | |
412 DCHECK(Proxy::IsImplThread()); | |
413 if (scheduler_on_impl_thread_) | |
414 scheduler_on_impl_thread_->SetCanDraw(can_draw); | |
415 } | |
416 | |
417 void SingleThreadProxy::NotifyReadyToActivate() { | |
418 TRACE_EVENT0("cc", "SingleThreadProxy::NotifyReadyToActivate"); | |
419 DebugScopedSetImplThread impl(this); | |
420 if (scheduler_on_impl_thread_) | |
421 scheduler_on_impl_thread_->NotifyReadyToActivate(); | |
422 } | |
423 | |
424 void SingleThreadProxy::NotifyReadyToDraw() { | |
425 } | |
426 | |
427 void SingleThreadProxy::SetNeedsRedrawOnImplThread() { | |
428 client_->ScheduleComposite(); | |
429 if (scheduler_on_impl_thread_) | |
430 scheduler_on_impl_thread_->SetNeedsRedraw(); | |
431 } | |
432 | |
433 void SingleThreadProxy::SetNeedsAnimateOnImplThread() { | |
434 client_->ScheduleComposite(); | |
435 if (scheduler_on_impl_thread_) | |
436 scheduler_on_impl_thread_->SetNeedsAnimate(); | |
437 } | |
438 | |
439 void SingleThreadProxy::SetNeedsPrepareTilesOnImplThread() { | |
440 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsPrepareTilesOnImplThread"); | |
441 if (scheduler_on_impl_thread_) | |
442 scheduler_on_impl_thread_->SetNeedsPrepareTiles(); | |
443 } | |
444 | |
445 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread( | |
446 const gfx::Rect& damage_rect) { | |
447 layer_tree_host_impl_->SetViewportDamage(damage_rect); | |
448 SetNeedsRedrawOnImplThread(); | |
449 } | |
450 | |
451 void SingleThreadProxy::SetNeedsCommitOnImplThread() { | |
452 client_->ScheduleComposite(); | |
453 if (scheduler_on_impl_thread_) | |
454 scheduler_on_impl_thread_->SetNeedsCommit(); | |
455 } | |
456 | |
457 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread( | |
458 scoped_ptr<AnimationEventsVector> events) { | |
459 TRACE_EVENT0( | |
460 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread"); | |
461 DCHECK(Proxy::IsImplThread()); | |
462 DebugScopedSetMainThread main(this); | |
463 layer_tree_host_->SetAnimationEvents(events.Pass()); | |
464 } | |
465 | |
466 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread( | |
467 size_t limit_bytes, | |
468 int priority_cutoff) { | |
469 DCHECK(IsImplThread()); | |
470 PrioritizedResourceManager* contents_texture_manager = | |
471 layer_tree_host_->contents_texture_manager(); | |
472 | |
473 ResourceProvider* resource_provider = | |
474 layer_tree_host_impl_->resource_provider(); | |
475 | |
476 if (!contents_texture_manager || !resource_provider) | |
477 return false; | |
478 | |
479 return contents_texture_manager->ReduceMemoryOnImplThread( | |
480 limit_bytes, priority_cutoff, resource_provider); | |
481 } | |
482 | |
483 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; } | |
484 | |
485 void SingleThreadProxy::DidActivateSyncTree() { | |
486 // Non-impl-side painting finishes commit in DoCommit. Impl-side painting | |
487 // defers until here to simulate SetNextCommitWaitsForActivation. | |
488 if (layer_tree_host_impl_->settings().impl_side_painting) { | |
489 // This is required because NotifyReadyToActivate gets called immediately | |
490 // after commit since single thread commits directly to the active tree. | |
491 layer_tree_host_impl_->SetRequiresHighResToDraw(); | |
492 | |
493 // Synchronously call to CommitComplete. Resetting | |
494 // |commit_blocking_task_runner| would make sure all tasks posted during | |
495 // commit/activation before CommitComplete. | |
496 CommitComplete(); | |
497 } | |
498 | |
499 timing_history_.DidActivateSyncTree(); | |
500 } | |
501 | |
502 void SingleThreadProxy::DidPrepareTiles() { | |
503 DCHECK(layer_tree_host_impl_->settings().impl_side_painting); | |
504 DCHECK(Proxy::IsImplThread()); | |
505 if (scheduler_on_impl_thread_) | |
506 scheduler_on_impl_thread_->DidPrepareTiles(); | |
507 } | |
508 | |
509 void SingleThreadProxy::DidCompletePageScaleAnimationOnImplThread() { | |
510 layer_tree_host_->DidCompletePageScaleAnimation(); | |
511 } | |
512 | |
513 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() { | |
514 DCHECK(IsImplThread()); | |
515 renderer_capabilities_for_main_thread_ = | |
516 layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities(); | |
517 } | |
518 | |
519 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() { | |
520 TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread"); | |
521 { | |
522 DebugScopedSetMainThread main(this); | |
523 // This must happen before we notify the scheduler as it may try to recreate | |
524 // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE. | |
525 layer_tree_host_->DidLoseOutputSurface(); | |
526 } | |
527 client_->DidAbortSwapBuffers(); | |
528 if (scheduler_on_impl_thread_) | |
529 scheduler_on_impl_thread_->DidLoseOutputSurface(); | |
530 } | |
531 | |
532 void SingleThreadProxy::CommitVSyncParameters(base::TimeTicks timebase, | |
533 base::TimeDelta interval) { | |
534 if (scheduler_on_impl_thread_) | |
535 scheduler_on_impl_thread_->CommitVSyncParameters(timebase, interval); | |
536 } | |
537 | |
538 void SingleThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { | |
539 if (scheduler_on_impl_thread_) | |
540 scheduler_on_impl_thread_->SetEstimatedParentDrawTime(draw_time); | |
541 } | |
542 | |
543 void SingleThreadProxy::DidSwapBuffersOnImplThread() { | |
544 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread"); | |
545 if (scheduler_on_impl_thread_) | |
546 scheduler_on_impl_thread_->DidSwapBuffers(); | |
547 client_->DidPostSwapBuffers(); | |
548 } | |
549 | |
550 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() { | |
551 TRACE_EVENT0("cc,benchmark", | |
552 "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread"); | |
553 if (scheduler_on_impl_thread_) | |
554 scheduler_on_impl_thread_->DidSwapBuffersComplete(); | |
555 layer_tree_host_->DidCompleteSwapBuffers(); | |
556 } | |
557 | |
558 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) { | |
559 TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::CompositeImmediately"); | |
560 DCHECK(Proxy::IsMainThread()); | |
561 base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true); | |
562 | |
563 if (layer_tree_host_->output_surface_lost()) { | |
564 RequestNewOutputSurface(); | |
565 // RequestNewOutputSurface could have synchronously created an output | |
566 // surface, so check again before returning. | |
567 if (layer_tree_host_->output_surface_lost()) | |
568 return; | |
569 } | |
570 | |
571 { | |
572 BeginFrameArgs begin_frame_args(BeginFrameArgs::Create( | |
573 BEGINFRAME_FROM_HERE, frame_begin_time, base::TimeTicks(), | |
574 BeginFrameArgs::DefaultInterval(), BeginFrameArgs::SYNCHRONOUS)); | |
575 DoBeginMainFrame(begin_frame_args); | |
576 DoCommit(); | |
577 | |
578 DCHECK_EQ(0u, layer_tree_host_->num_queued_swap_promises()) | |
579 << "Commit should always succeed and transfer promises."; | |
580 } | |
581 | |
582 { | |
583 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this)); | |
584 if (layer_tree_host_impl_->settings().impl_side_painting) { | |
585 layer_tree_host_impl_->ActivateSyncTree(); | |
586 DCHECK(!layer_tree_host_impl_->active_tree() | |
587 ->needs_update_draw_properties()); | |
588 layer_tree_host_impl_->PrepareTiles(); | |
589 layer_tree_host_impl_->SynchronouslyInitializeAllTiles(); | |
590 } | |
591 | |
592 DoAnimate(); | |
593 | |
594 LayerTreeHostImpl::FrameData frame; | |
595 DoComposite(frame_begin_time, &frame); | |
596 | |
597 // DoComposite could abort, but because this is a synchronous composite | |
598 // another draw will never be scheduled, so break remaining promises. | |
599 layer_tree_host_impl_->active_tree()->BreakSwapPromises( | |
600 SwapPromise::SWAP_FAILS); | |
601 } | |
602 } | |
603 | |
604 void SingleThreadProxy::ForceSerializeOnSwapBuffers() { | |
605 { | |
606 DebugScopedSetImplThread impl(this); | |
607 if (layer_tree_host_impl_->renderer()) { | |
608 DCHECK(!layer_tree_host_->output_surface_lost()); | |
609 layer_tree_host_impl_->renderer()->DoNoOp(); | |
610 } | |
611 } | |
612 } | |
613 | |
614 bool SingleThreadProxy::SupportsImplScrolling() const { | |
615 return false; | |
616 } | |
617 | |
618 bool SingleThreadProxy::ShouldComposite() const { | |
619 DCHECK(Proxy::IsImplThread()); | |
620 return layer_tree_host_impl_->visible() && | |
621 layer_tree_host_impl_->CanDraw(); | |
622 } | |
623 | |
624 void SingleThreadProxy::ScheduleRequestNewOutputSurface() { | |
625 if (output_surface_creation_callback_.IsCancelled() && | |
626 !output_surface_creation_requested_) { | |
627 output_surface_creation_callback_.Reset( | |
628 base::Bind(&SingleThreadProxy::RequestNewOutputSurface, | |
629 weak_factory_.GetWeakPtr())); | |
630 MainThreadTaskRunner()->PostTask( | |
631 FROM_HERE, output_surface_creation_callback_.callback()); | |
632 } | |
633 } | |
634 | |
635 DrawResult SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time, | |
636 LayerTreeHostImpl::FrameData* frame) { | |
637 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite"); | |
638 DCHECK(!layer_tree_host_->output_surface_lost()); | |
639 | |
640 DrawResult draw_result; | |
641 bool draw_frame; | |
642 { | |
643 DebugScopedSetImplThread impl(this); | |
644 base::AutoReset<bool> mark_inside(&inside_draw_, true); | |
645 | |
646 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
647 // is fixed. | |
648 tracked_objects::ScopedTracker tracking_profile1( | |
649 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
650 "461509 SingleThreadProxy::DoComposite1")); | |
651 | |
652 // We guard PrepareToDraw() with CanDraw() because it always returns a valid | |
653 // frame, so can only be used when such a frame is possible. Since | |
654 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on | |
655 // CanDraw() as well. | |
656 if (!ShouldComposite()) { | |
657 return DRAW_ABORTED_CANT_DRAW; | |
658 } | |
659 | |
660 timing_history_.DidStartDrawing(); | |
661 | |
662 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
663 // is fixed. | |
664 tracked_objects::ScopedTracker tracking_profile2( | |
665 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
666 "461509 SingleThreadProxy::DoComposite2")); | |
667 draw_result = layer_tree_host_impl_->PrepareToDraw(frame); | |
668 draw_frame = draw_result == DRAW_SUCCESS; | |
669 if (draw_frame) { | |
670 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
671 // is fixed. | |
672 tracked_objects::ScopedTracker tracking_profile3( | |
673 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
674 "461509 SingleThreadProxy::DoComposite3")); | |
675 layer_tree_host_impl_->DrawLayers(frame, frame_begin_time); | |
676 } | |
677 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
678 // is fixed. | |
679 tracked_objects::ScopedTracker tracking_profile4( | |
680 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
681 "461509 SingleThreadProxy::DoComposite4")); | |
682 layer_tree_host_impl_->DidDrawAllLayers(*frame); | |
683 | |
684 bool start_ready_animations = draw_frame; | |
685 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
686 // is fixed. | |
687 tracked_objects::ScopedTracker tracking_profile5( | |
688 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
689 "461509 SingleThreadProxy::DoComposite5")); | |
690 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations); | |
691 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
692 // is fixed. | |
693 tracked_objects::ScopedTracker tracking_profile6( | |
694 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
695 "461509 SingleThreadProxy::DoComposite6")); | |
696 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame(); | |
697 | |
698 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
699 // is fixed. | |
700 tracked_objects::ScopedTracker tracking_profile7( | |
701 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
702 "461509 SingleThreadProxy::DoComposite7")); | |
703 timing_history_.DidFinishDrawing(); | |
704 } | |
705 | |
706 if (draw_frame) { | |
707 DebugScopedSetImplThread impl(this); | |
708 | |
709 // This CapturePostTasks should be destroyed before | |
710 // DidCommitAndDrawFrame() is called since that goes out to the | |
711 // embedder, | |
712 // and we want the embedder to receive its callbacks before that. | |
713 // NOTE: This maintains consistent ordering with the ThreadProxy since | |
714 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread | |
715 // there as the main thread is not blocked, so any posted tasks inside | |
716 // the swap buffers will execute first. | |
717 DebugScopedSetMainThreadBlocked main_thread_blocked(this); | |
718 | |
719 BlockingTaskRunner::CapturePostTasks blocked( | |
720 blocking_main_thread_task_runner()); | |
721 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 | |
722 // is fixed. | |
723 tracked_objects::ScopedTracker tracking_profile8( | |
724 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
725 "461509 SingleThreadProxy::DoComposite8")); | |
726 layer_tree_host_impl_->SwapBuffers(*frame); | |
727 } | |
728 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is | |
729 // fixed. | |
730 tracked_objects::ScopedTracker tracking_profile9( | |
731 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
732 "461509 SingleThreadProxy::DoComposite9")); | |
733 DidCommitAndDrawFrame(); | |
734 | |
735 return draw_result; | |
736 } | |
737 | |
738 void SingleThreadProxy::DidCommitAndDrawFrame() { | |
739 if (next_frame_is_newly_committed_frame_) { | |
740 DebugScopedSetMainThread main(this); | |
741 next_frame_is_newly_committed_frame_ = false; | |
742 layer_tree_host_->DidCommitAndDrawFrame(); | |
743 } | |
744 } | |
745 | |
746 bool SingleThreadProxy::MainFrameWillHappenForTesting() { | |
747 return false; | |
748 } | |
749 | |
750 void SingleThreadProxy::SetChildrenNeedBeginFrames( | |
751 bool children_need_begin_frames) { | |
752 scheduler_on_impl_thread_->SetChildrenNeedBeginFrames( | |
753 children_need_begin_frames); | |
754 } | |
755 | |
756 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) { | |
757 layer_tree_host_impl_->WillBeginImplFrame(args); | |
758 } | |
759 | |
760 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() { | |
761 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame"); | |
762 // Although this proxy is single-threaded, it's problematic to synchronously | |
763 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This | |
764 // could cause a commit to occur in between a series of SetNeedsCommit calls | |
765 // (i.e. property modifications) causing some to fall on one frame and some to | |
766 // fall on the next. Doing it asynchronously instead matches the semantics of | |
767 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a | |
768 // synchronous commit. | |
769 MainThreadTaskRunner()->PostTask( | |
770 FROM_HERE, | |
771 base::Bind(&SingleThreadProxy::BeginMainFrame, | |
772 weak_factory_.GetWeakPtr())); | |
773 } | |
774 | |
775 void SingleThreadProxy::SendBeginMainFrameNotExpectedSoon() { | |
776 layer_tree_host_->BeginMainFrameNotExpectedSoon(); | |
777 } | |
778 | |
779 void SingleThreadProxy::BeginMainFrame() { | |
780 if (defer_commits_) { | |
781 TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit", | |
782 TRACE_EVENT_SCOPE_THREAD); | |
783 BeginMainFrameAbortedOnImplThread( | |
784 CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT); | |
785 return; | |
786 } | |
787 | |
788 // This checker assumes NotifyReadyToCommit in this stack causes a synchronous | |
789 // commit. | |
790 ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_); | |
791 | |
792 if (!layer_tree_host_->visible()) { | |
793 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD); | |
794 BeginMainFrameAbortedOnImplThread( | |
795 CommitEarlyOutReason::ABORTED_NOT_VISIBLE); | |
796 return; | |
797 } | |
798 | |
799 if (layer_tree_host_->output_surface_lost()) { | |
800 TRACE_EVENT_INSTANT0( | |
801 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD); | |
802 BeginMainFrameAbortedOnImplThread( | |
803 CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST); | |
804 return; | |
805 } | |
806 | |
807 const BeginFrameArgs& begin_frame_args = | |
808 layer_tree_host_impl_->CurrentBeginFrameArgs(); | |
809 DoBeginMainFrame(begin_frame_args); | |
810 } | |
811 | |
812 void SingleThreadProxy::DoBeginMainFrame( | |
813 const BeginFrameArgs& begin_frame_args) { | |
814 layer_tree_host_->WillBeginMainFrame(); | |
815 layer_tree_host_->BeginMainFrame(begin_frame_args); | |
816 layer_tree_host_->AnimateLayers(begin_frame_args.frame_time); | |
817 layer_tree_host_->Layout(); | |
818 | |
819 if (PrioritizedResourceManager* contents_texture_manager = | |
820 layer_tree_host_->contents_texture_manager()) { | |
821 contents_texture_manager->UnlinkAndClearEvictedBackings(); | |
822 contents_texture_manager->SetMaxMemoryLimitBytes( | |
823 layer_tree_host_impl_->memory_allocation_limit_bytes()); | |
824 contents_texture_manager->SetExternalPriorityCutoff( | |
825 layer_tree_host_impl_->memory_allocation_priority_cutoff()); | |
826 } | |
827 | |
828 DCHECK(!queue_for_commit_); | |
829 queue_for_commit_ = make_scoped_ptr(new ResourceUpdateQueue); | |
830 | |
831 layer_tree_host_->UpdateLayers(queue_for_commit_.get()); | |
832 | |
833 timing_history_.DidBeginMainFrame(); | |
834 | |
835 // TODO(enne): SingleThreadProxy does not support cancelling commits yet, | |
836 // search for CommitEarlyOutReason::FINISHED_NO_UPDATES inside | |
837 // thread_proxy.cc | |
838 if (scheduler_on_impl_thread_) { | |
839 scheduler_on_impl_thread_->NotifyBeginMainFrameStarted(); | |
840 scheduler_on_impl_thread_->NotifyReadyToCommit(); | |
841 } | |
842 } | |
843 | |
844 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread( | |
845 CommitEarlyOutReason reason) { | |
846 DebugScopedSetImplThread impl(this); | |
847 DCHECK(scheduler_on_impl_thread_->CommitPending()); | |
848 DCHECK(!layer_tree_host_impl_->pending_tree()); | |
849 | |
850 layer_tree_host_impl_->BeginMainFrameAborted(reason); | |
851 scheduler_on_impl_thread_->BeginMainFrameAborted(reason); | |
852 } | |
853 | |
854 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() { | |
855 DebugScopedSetImplThread impl(this); | |
856 LayerTreeHostImpl::FrameData frame; | |
857 return DoComposite(layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time, | |
858 &frame); | |
859 } | |
860 | |
861 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() { | |
862 NOTREACHED(); | |
863 return INVALID_RESULT; | |
864 } | |
865 | |
866 void SingleThreadProxy::ScheduledActionCommit() { | |
867 DebugScopedSetMainThread main(this); | |
868 DoCommit(); | |
869 } | |
870 | |
871 void SingleThreadProxy::ScheduledActionAnimate() { | |
872 TRACE_EVENT0("cc", "ScheduledActionAnimate"); | |
873 DebugScopedSetImplThread impl(this); | |
874 DoAnimate(); | |
875 } | |
876 | |
877 void SingleThreadProxy::ScheduledActionActivateSyncTree() { | |
878 DebugScopedSetImplThread impl(this); | |
879 layer_tree_host_impl_->ActivateSyncTree(); | |
880 } | |
881 | |
882 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() { | |
883 DebugScopedSetMainThread main(this); | |
884 DCHECK(scheduler_on_impl_thread_); | |
885 // If possible, create the output surface in a post task. Synchronously | |
886 // creating the output surface makes tests more awkward since this differs | |
887 // from the ThreadProxy behavior. However, sometimes there is no | |
888 // task runner. | |
889 if (Proxy::MainThreadTaskRunner()) { | |
890 ScheduleRequestNewOutputSurface(); | |
891 } else { | |
892 RequestNewOutputSurface(); | |
893 } | |
894 } | |
895 | |
896 void SingleThreadProxy::ScheduledActionPrepareTiles() { | |
897 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionPrepareTiles"); | |
898 DCHECK(layer_tree_host_impl_->settings().impl_side_painting); | |
899 DebugScopedSetImplThread impl(this); | |
900 layer_tree_host_impl_->PrepareTiles(); | |
901 } | |
902 | |
903 void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) { | |
904 } | |
905 | |
906 base::TimeDelta SingleThreadProxy::DrawDurationEstimate() { | |
907 return timing_history_.DrawDurationEstimate(); | |
908 } | |
909 | |
910 base::TimeDelta SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() { | |
911 return timing_history_.BeginMainFrameToCommitDurationEstimate(); | |
912 } | |
913 | |
914 base::TimeDelta SingleThreadProxy::CommitToActivateDurationEstimate() { | |
915 return timing_history_.CommitToActivateDurationEstimate(); | |
916 } | |
917 | |
918 void SingleThreadProxy::DidBeginImplFrameDeadline() { | |
919 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame(); | |
920 } | |
921 | |
922 void SingleThreadProxy::SendBeginFramesToChildren(const BeginFrameArgs& args) { | |
923 layer_tree_host_->SendBeginFramesToChildren(args); | |
924 } | |
925 | |
926 } // namespace cc | |
OLD | NEW |