OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
vmpstr
2015/12/04 00:25:40
I assume this is mostly a copy of the thread proxy
Khushal
2015/12/04 22:45:22
Yes. This has been moved from ThreadProxy as-is.
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cc/trees/proxy_impl.h" | |
6 | |
7 #include <algorithm> | |
8 #include <string> | |
9 | |
10 #include "base/auto_reset.h" | |
11 #include "base/bind.h" | |
12 #include "base/trace_event/trace_event.h" | |
13 #include "base/trace_event/trace_event_argument.h" | |
14 #include "base/trace_event/trace_event_synthetic_delay.h" | |
15 #include "cc/debug/benchmark_instrumentation.h" | |
16 #include "cc/debug/devtools_instrumentation.h" | |
17 #include "cc/input/input_handler.h" | |
18 #include "cc/input/top_controls_manager.h" | |
19 #include "cc/output/context_provider.h" | |
20 #include "cc/output/output_surface.h" | |
21 #include "cc/output/swap_promise.h" | |
22 #include "cc/quads/draw_quad.h" | |
23 #include "cc/scheduler/commit_earlyout_reason.h" | |
24 #include "cc/scheduler/compositor_timing_history.h" | |
25 #include "cc/scheduler/scheduler.h" | |
26 #include "cc/trees/blocking_task_runner.h" | |
27 #include "cc/trees/layer_tree_host.h" | |
28 #include "cc/trees/layer_tree_impl.h" | |
29 #include "cc/trees/scoped_abort_remaining_swap_promises.h" | |
30 #include "cc/trees/task_runner_provider.h" | |
31 #include "gpu/command_buffer/client/gles2_interface.h" | |
32 | |
33 namespace cc { | |
34 | |
35 namespace { | |
36 | |
37 // Measured in seconds. | |
38 const double kSmoothnessTakesPriorityExpirationDelay = 0.25; | |
39 | |
40 unsigned int nextBeginFrameId = 0; | |
41 | |
42 } // namespace | |
43 | |
44 scoped_ptr<ProxyImpl> ProxyImpl::Create( | |
45 ChannelImpl* channel_impl, | |
46 LayerTreeHost* layer_tree_host, | |
47 TaskRunnerProvider* task_runner_provider, | |
48 scoped_ptr<BeginFrameSource> external_begin_frame_source) { | |
49 return make_scoped_ptr(new ProxyImpl(channel_impl, layer_tree_host, | |
50 task_runner_provider, | |
51 std::move(external_begin_frame_source))); | |
52 } | |
53 | |
54 ProxyImpl::ProxyImpl(ChannelImpl* channel_impl, | |
55 LayerTreeHost* layer_tree_host, | |
56 TaskRunnerProvider* task_runner_provider, | |
57 scoped_ptr<BeginFrameSource> external_begin_frame_source) | |
58 : layer_tree_host_id_(layer_tree_host->id()), | |
59 next_commit_waits_for_activation_(false), | |
60 commit_completion_event_(nullptr), | |
61 next_frame_is_newly_committed_frame_(false), | |
62 inside_draw_(false), | |
63 input_throttled_until_commit_(false), | |
64 task_runner_provider_(task_runner_provider), | |
65 smoothness_priority_expiration_notifier_( | |
66 task_runner_provider->ImplThreadTaskRunner(), | |
67 base::Bind(&ProxyImpl::RenewTreePriority, base::Unretained(this)), | |
68 base::TimeDelta::FromSeconds( | |
69 kSmoothnessTakesPriorityExpirationDelay)), | |
70 external_begin_frame_source_(std::move(external_begin_frame_source)), | |
71 rendering_stats_instrumentation_( | |
72 layer_tree_host->rendering_stats_instrumentation()), | |
73 channel_impl_(channel_impl) { | |
74 TRACE_EVENT0("cc", "ProxyImpl::ProxyImpl"); | |
75 DCHECK(IsImplThread()); | |
76 DCHECK(IsMainThreadBlocked()); | |
77 | |
78 layer_tree_host_impl_ = layer_tree_host->CreateLayerTreeHostImpl(this); | |
79 | |
80 SchedulerSettings scheduler_settings( | |
81 layer_tree_host->settings().ToSchedulerSettings()); | |
82 | |
83 scoped_ptr<CompositorTimingHistory> compositor_timing_history( | |
84 new CompositorTimingHistory(CompositorTimingHistory::RENDERER_UMA, | |
85 rendering_stats_instrumentation_)); | |
86 | |
87 scheduler_ = Scheduler::Create(this, scheduler_settings, layer_tree_host_id_, | |
88 task_runner_provider_->ImplThreadTaskRunner(), | |
89 external_begin_frame_source_.get(), | |
90 std::move(compositor_timing_history)); | |
91 | |
92 DCHECK_EQ(scheduler_->visible(), layer_tree_host_impl_->visible()); | |
93 } | |
94 | |
95 ProxyImpl::BlockedMainCommitOnly::BlockedMainCommitOnly() | |
96 : layer_tree_host(nullptr) {} | |
97 | |
98 ProxyImpl::BlockedMainCommitOnly::~BlockedMainCommitOnly() {} | |
99 | |
100 ProxyImpl::~ProxyImpl() { | |
101 TRACE_EVENT0("cc", "ProxyImpl::~ProxyImpl"); | |
102 DCHECK(IsImplThread()); | |
103 DCHECK(IsMainThreadBlocked()); | |
104 | |
105 scheduler_ = nullptr; | |
106 external_begin_frame_source_ = nullptr; | |
107 layer_tree_host_impl_ = nullptr; | |
108 // We need to explicitly shutdown the notifier to destroy any weakptrs it is | |
109 // holding while still on the compositor thread. This also ensures any | |
110 // callbacks holding a ProxyImpl pointer are cancelled. | |
111 smoothness_priority_expiration_notifier_.Shutdown(); | |
112 } | |
113 | |
114 void ProxyImpl::SetThrottleFrameProductionOnImpl(bool throttle) { | |
115 TRACE_EVENT1("cc", "ProxyImpl::SetThrottleFrameProductionOnImplThread", | |
116 "throttle", throttle); | |
117 DCHECK(IsImplThread()); | |
118 scheduler_->SetThrottleFrameProduction(throttle); | |
119 } | |
120 | |
121 void ProxyImpl::UpdateTopControlsStateOnImpl(TopControlsState constraints, | |
122 TopControlsState current, | |
123 bool animate) { | |
124 DCHECK(IsImplThread()); | |
125 layer_tree_host_impl_->top_controls_manager()->UpdateTopControlsState( | |
126 constraints, current, animate); | |
127 } | |
128 | |
129 void ProxyImpl::InitializeOutputSurfaceOnImpl(OutputSurface* output_surface) { | |
130 TRACE_EVENT0("cc", "ProxyImpl::InitializeOutputSurfaceOnImplThread"); | |
131 DCHECK(IsImplThread()); | |
132 | |
133 LayerTreeHostImpl* host_impl = layer_tree_host_impl_.get(); | |
134 bool success = host_impl->InitializeRenderer(output_surface); | |
135 RendererCapabilities capabilities; | |
136 if (success) { | |
137 capabilities = | |
138 host_impl->GetRendererCapabilities().MainThreadCapabilities(); | |
139 } | |
140 | |
141 channel_impl_->DidInitializeOutputSurface(success, capabilities); | |
142 | |
143 if (success) | |
144 scheduler_->DidCreateAndInitializeOutputSurface(); | |
145 } | |
146 | |
147 void ProxyImpl::MainThreadHasStoppedFlingingOnImpl() { | |
148 DCHECK(IsImplThread()); | |
149 layer_tree_host_impl_->MainThreadHasStoppedFlinging(); | |
150 } | |
151 | |
152 void ProxyImpl::SetInputThrottledUntilCommitOnImpl(bool is_throttled) { | |
153 DCHECK(IsImplThread()); | |
154 if (is_throttled == input_throttled_until_commit_) | |
155 return; | |
156 input_throttled_until_commit_ = is_throttled; | |
157 RenewTreePriority(); | |
158 } | |
159 | |
160 void ProxyImpl::SetDeferCommitsOnImpl(bool defer_commits) const { | |
161 DCHECK(IsImplThread()); | |
162 scheduler_->SetDeferCommits(defer_commits); | |
163 } | |
164 | |
165 void ProxyImpl::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) { | |
166 DCHECK(IsImplThread()); | |
167 SetNeedsRedrawRectOnImplThread(damage_rect); | |
168 } | |
169 | |
170 void ProxyImpl::SetNeedsCommitOnImpl() { | |
171 DCHECK(IsImplThread()); | |
172 SetNeedsCommitOnImplThread(); | |
173 } | |
174 | |
175 void ProxyImpl::BeginMainFrameAbortedOnImpl( | |
176 CommitEarlyOutReason reason, | |
177 base::TimeTicks main_thread_start_time) { | |
178 TRACE_EVENT1("cc", "ProxyImpl::BeginMainFrameAbortedOnImplThread", "reason", | |
179 CommitEarlyOutReasonToString(reason)); | |
180 DCHECK(IsImplThread()); | |
181 DCHECK(scheduler_->CommitPending()); | |
182 DCHECK(!layer_tree_host_impl_->pending_tree()); | |
183 | |
184 if (CommitEarlyOutHandledCommit(reason)) { | |
185 SetInputThrottledUntilCommitOnImpl(false); | |
186 last_processed_begin_main_frame_args_ = last_begin_main_frame_args_; | |
187 } | |
188 layer_tree_host_impl_->BeginMainFrameAborted(reason); | |
189 scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time); | |
190 scheduler_->BeginMainFrameAborted(reason); | |
191 } | |
192 | |
193 void ProxyImpl::FinishAllRenderingOnImpl(CompletionEvent* completion) { | |
194 TRACE_EVENT0("cc", "ProxyImpl::FinishAllRenderingOnImplThread"); | |
195 DCHECK(IsImplThread()); | |
196 layer_tree_host_impl_->FinishAllRendering(); | |
197 completion->Signal(); | |
198 } | |
199 | |
200 void ProxyImpl::SetVisibleOnImpl(bool visible) { | |
201 TRACE_EVENT1("cc", "ProxyImpl::SetVisibleOnImplThread", "visible", visible); | |
202 DCHECK(IsImplThread()); | |
203 layer_tree_host_impl_->SetVisible(visible); | |
204 scheduler_->SetVisible(visible); | |
205 } | |
206 | |
207 void ProxyImpl::ReleaseOutputSurfaceOnImpl(CompletionEvent* completion) { | |
208 DCHECK(IsImplThread()); | |
209 | |
210 // Unlike DidLoseOutputSurfaceOnImplThread, we don't need to call | |
211 // LayerTreeHost::DidLoseOutputSurface since it already knows. | |
212 scheduler_->DidLoseOutputSurface(); | |
213 layer_tree_host_impl_->ReleaseOutputSurface(); | |
214 completion->Signal(); | |
215 } | |
216 | |
217 void ProxyImpl::FinishGLOnImpl(CompletionEvent* completion) { | |
218 TRACE_EVENT0("cc", "ProxyImpl::FinishGLOnImplThread"); | |
219 DCHECK(IsImplThread()); | |
220 if (layer_tree_host_impl_->output_surface()) { | |
221 ContextProvider* context_provider = | |
222 layer_tree_host_impl_->output_surface()->context_provider(); | |
223 if (context_provider) | |
224 context_provider->ContextGL()->Finish(); | |
225 } | |
226 completion->Signal(); | |
227 } | |
228 | |
229 void ProxyImpl::MainFrameWillHappenOnImplForTesting( | |
230 CompletionEvent* completion, | |
231 bool* main_frame_will_happen) { | |
232 DCHECK(IsImplThread()); | |
233 if (layer_tree_host_impl_->output_surface()) { | |
234 *main_frame_will_happen = scheduler_->MainFrameForTestingWillHappen(); | |
235 } else { | |
236 *main_frame_will_happen = false; | |
237 } | |
238 completion->Signal(); | |
239 } | |
240 | |
241 void ProxyImpl::StartCommitOnImpl(CompletionEvent* completion, | |
242 LayerTreeHost* layer_tree_host, | |
243 base::TimeTicks main_thread_start_time, | |
244 bool hold_commit_for_activation) { | |
245 TRACE_EVENT0("cc", "ProxyImpl::StartCommitOnImplThread"); | |
246 DCHECK(!commit_completion_event_); | |
247 DCHECK(IsImplThread() && IsMainThreadBlocked()); | |
248 DCHECK(scheduler_); | |
249 DCHECK(scheduler_->CommitPending()); | |
250 | |
251 if (hold_commit_for_activation) { | |
252 // This commit may be aborted. Store the value for | |
253 // hold_commit_for_activation so that whenever the next commit is started, | |
254 // the main thread will be unblocked only after pending tree activation. | |
255 next_commit_waits_for_activation_ = hold_commit_for_activation; | |
256 } | |
257 | |
258 if (!layer_tree_host_impl_) { | |
259 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoLayerTree", | |
260 TRACE_EVENT_SCOPE_THREAD); | |
261 completion->Signal(); | |
262 return; | |
263 } | |
264 | |
265 // Ideally, we should inform to impl thread when BeginMainFrame is started. | |
266 // But, we can avoid a PostTask in here. | |
267 scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time); | |
268 commit_completion_event_ = completion; | |
269 DCHECK(!blocked_main_commit().layer_tree_host); | |
270 blocked_main_commit().layer_tree_host = layer_tree_host; | |
271 scheduler_->NotifyReadyToCommit(); | |
272 } | |
273 | |
274 bool ProxyImpl::HasCommitCompletionEventForTesting() const { | |
275 return commit_completion_event_ != nullptr; | |
276 } | |
277 | |
278 bool ProxyImpl::GetNextCommitWaitsForActivationForTesting() const { | |
279 return next_commit_waits_for_activation_; | |
280 } | |
281 | |
282 void ProxyImpl::UpdateRendererCapabilitiesOnImplThread() { | |
283 DCHECK(IsImplThread()); | |
284 channel_impl_->SetRendererCapabilitiesMainCopy( | |
285 layer_tree_host_impl_->GetRendererCapabilities() | |
286 .MainThreadCapabilities()); | |
287 } | |
288 | |
289 void ProxyImpl::DidLoseOutputSurfaceOnImplThread() { | |
290 TRACE_EVENT0("cc", "ProxyImpl::DidLoseOutputSurfaceOnImplThread"); | |
291 DCHECK(IsImplThread()); | |
292 channel_impl_->DidLoseOutputSurface(); | |
293 scheduler_->DidLoseOutputSurface(); | |
294 } | |
295 | |
296 void ProxyImpl::CommitVSyncParameters(base::TimeTicks timebase, | |
297 base::TimeDelta interval) { | |
298 DCHECK(IsImplThread()); | |
299 scheduler_->CommitVSyncParameters(timebase, interval); | |
300 } | |
301 | |
302 void ProxyImpl::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { | |
303 DCHECK(IsImplThread()); | |
304 scheduler_->SetEstimatedParentDrawTime(draw_time); | |
305 } | |
306 | |
307 void ProxyImpl::DidSwapBuffersOnImplThread() { | |
308 DCHECK(IsImplThread()); | |
309 scheduler_->DidSwapBuffers(); | |
310 } | |
311 | |
312 void ProxyImpl::DidSwapBuffersCompleteOnImplThread() { | |
313 TRACE_EVENT0("cc,benchmark", "ProxyImpl::DidSwapBuffersCompleteOnImplThread"); | |
314 DCHECK(IsImplThread()); | |
315 scheduler_->DidSwapBuffersComplete(); | |
316 channel_impl_->DidCompleteSwapBuffers(); | |
317 } | |
318 | |
319 void ProxyImpl::OnResourcelessSoftareDrawStateChanged(bool resourceless_draw) { | |
320 DCHECK(IsImplThread()); | |
321 scheduler_->SetResourcelessSoftareDraw(resourceless_draw); | |
322 } | |
323 | |
324 void ProxyImpl::OnCanDrawStateChanged(bool can_draw) { | |
325 TRACE_EVENT1("cc", "ProxyImpl::OnCanDrawStateChanged", "can_draw", can_draw); | |
326 DCHECK(IsImplThread()); | |
327 scheduler_->SetCanDraw(can_draw); | |
328 } | |
329 | |
330 void ProxyImpl::NotifyReadyToActivate() { | |
331 TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToActivate"); | |
332 DCHECK(IsImplThread()); | |
333 scheduler_->NotifyReadyToActivate(); | |
334 } | |
335 | |
336 void ProxyImpl::NotifyReadyToDraw() { | |
337 TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToDraw"); | |
338 DCHECK(IsImplThread()); | |
339 scheduler_->NotifyReadyToDraw(); | |
340 } | |
341 | |
342 void ProxyImpl::SetNeedsRedrawOnImplThread() { | |
343 TRACE_EVENT0("cc", "ProxyImpl::SetNeedsRedrawOnImplThread"); | |
344 DCHECK(IsImplThread()); | |
345 scheduler_->SetNeedsRedraw(); | |
346 } | |
347 | |
348 void ProxyImpl::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) { | |
349 DCHECK(IsImplThread()); | |
350 layer_tree_host_impl_->SetViewportDamage(damage_rect); | |
351 SetNeedsRedrawOnImplThread(); | |
352 } | |
353 | |
354 void ProxyImpl::SetNeedsAnimateOnImplThread() { | |
355 TRACE_EVENT0("cc", "ProxyImpl::SetNeedsAnimateOnImplThread"); | |
356 DCHECK(IsImplThread()); | |
357 scheduler_->SetNeedsAnimate(); | |
358 } | |
359 | |
360 void ProxyImpl::SetNeedsPrepareTilesOnImplThread() { | |
361 DCHECK(IsImplThread()); | |
362 scheduler_->SetNeedsPrepareTiles(); | |
363 } | |
364 | |
365 void ProxyImpl::SetNeedsCommitOnImplThread() { | |
366 TRACE_EVENT0("cc", "ProxyImpl::SetNeedsCommitOnImplThread"); | |
367 DCHECK(IsImplThread()); | |
368 scheduler_->SetNeedsBeginMainFrame(); | |
369 } | |
370 | |
371 void ProxyImpl::SetVideoNeedsBeginFrames(bool needs_begin_frames) { | |
372 TRACE_EVENT1("cc", "ProxyImpl::SetVideoNeedsBeginFrames", | |
373 "needs_begin_frames", needs_begin_frames); | |
374 DCHECK(IsImplThread()); | |
375 // In tests the layer tree is destroyed after the scheduler is. | |
376 if (scheduler_) | |
377 scheduler_->SetVideoNeedsBeginFrames(needs_begin_frames); | |
378 } | |
379 | |
380 void ProxyImpl::PostAnimationEventsToMainThreadOnImplThread( | |
381 scoped_ptr<AnimationEventsVector> events) { | |
382 TRACE_EVENT0("cc", "ProxyImpl::PostAnimationEventsToMainThreadOnImplThread"); | |
383 DCHECK(IsImplThread()); | |
384 channel_impl_->SetAnimationEvents(std::move(events)); | |
385 } | |
386 | |
387 bool ProxyImpl::IsInsideDraw() { | |
388 return inside_draw_; | |
389 } | |
390 | |
391 void ProxyImpl::RenewTreePriority() { | |
392 DCHECK(IsImplThread()); | |
393 bool smoothness_takes_priority = | |
394 layer_tree_host_impl_->pinch_gesture_active() || | |
395 layer_tree_host_impl_->page_scale_animation_active() || | |
396 layer_tree_host_impl_->IsActivelyScrolling(); | |
397 | |
398 // Schedule expiration if smoothness currently takes priority. | |
399 if (smoothness_takes_priority) | |
400 smoothness_priority_expiration_notifier_.Schedule(); | |
401 | |
402 // We use the same priority for both trees by default. | |
403 TreePriority tree_priority = SAME_PRIORITY_FOR_BOTH_TREES; | |
404 | |
405 // Smoothness takes priority if we have an expiration for it scheduled. | |
406 if (smoothness_priority_expiration_notifier_.HasPendingNotification()) | |
407 tree_priority = SMOOTHNESS_TAKES_PRIORITY; | |
408 | |
409 // New content always takes priority when there is an invalid viewport size or | |
410 // ui resources have been evicted. | |
411 if (layer_tree_host_impl_->active_tree()->ViewportSizeInvalid() || | |
412 layer_tree_host_impl_->EvictedUIResourcesExist() || | |
413 input_throttled_until_commit_) { | |
414 // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active | |
415 // tree might be freed. We need to set RequiresHighResToDraw to ensure that | |
416 // high res tiles will be required to activate pending tree. | |
417 layer_tree_host_impl_->SetRequiresHighResToDraw(); | |
418 tree_priority = NEW_CONTENT_TAKES_PRIORITY; | |
419 } | |
420 | |
421 layer_tree_host_impl_->SetTreePriority(tree_priority); | |
422 | |
423 // Only put the scheduler in impl latency prioritization mode if we don't | |
424 // have a scroll listener. This gives the scroll listener a better chance of | |
425 // handling scroll updates within the same frame. The tree itself is still | |
426 // kept in prefer smoothness mode to allow checkerboarding. | |
427 ScrollHandlerState scroll_handler_state = | |
428 layer_tree_host_impl_->scroll_affects_scroll_handler() | |
429 ? ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER | |
430 : ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER; | |
431 scheduler_->SetTreePrioritiesAndScrollState(tree_priority, | |
432 scroll_handler_state); | |
433 | |
434 // Notify the the client of this compositor via the output surface. | |
435 // TODO(epenner): Route this to compositor-thread instead of output-surface | |
436 // after GTFO refactor of compositor-thread (http://crbug/170828). | |
437 if (layer_tree_host_impl_->output_surface()) { | |
438 layer_tree_host_impl_->output_surface()->UpdateSmoothnessTakesPriority( | |
439 tree_priority == SMOOTHNESS_TAKES_PRIORITY); | |
440 } | |
441 } | |
442 | |
443 void ProxyImpl::PostDelayedAnimationTaskOnImplThread(const base::Closure& task, | |
444 base::TimeDelta delay) { | |
445 DCHECK(IsImplThread()); | |
446 task_runner_provider_->ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, | |
447 task, delay); | |
448 } | |
449 | |
450 void ProxyImpl::DidActivateSyncTree() { | |
451 TRACE_EVENT0("cc", "ProxyImpl::DidActivateSyncTreeOnImplThread"); | |
452 DCHECK(IsImplThread()); | |
453 | |
454 if (next_commit_waits_for_activation_) { | |
455 TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation", | |
456 TRACE_EVENT_SCOPE_THREAD); | |
457 DCHECK(commit_completion_event_); | |
458 commit_completion_event_->Signal(); | |
459 commit_completion_event_ = nullptr; | |
460 next_commit_waits_for_activation_ = false; | |
461 } | |
462 | |
463 last_processed_begin_main_frame_args_ = last_begin_main_frame_args_; | |
464 } | |
465 | |
466 void ProxyImpl::WillPrepareTiles() { | |
467 DCHECK(IsImplThread()); | |
468 scheduler_->WillPrepareTiles(); | |
469 } | |
470 | |
471 void ProxyImpl::DidPrepareTiles() { | |
472 DCHECK(IsImplThread()); | |
473 scheduler_->DidPrepareTiles(); | |
474 } | |
475 | |
476 void ProxyImpl::DidCompletePageScaleAnimationOnImplThread() { | |
477 DCHECK(IsImplThread()); | |
478 channel_impl_->DidCompletePageScaleAnimation(); | |
479 } | |
480 | |
481 void ProxyImpl::OnDrawForOutputSurface() { | |
482 DCHECK(IsImplThread()); | |
483 scheduler_->OnDrawForOutputSurface(); | |
484 } | |
485 | |
486 void ProxyImpl::PostFrameTimingEventsOnImplThread( | |
487 scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events, | |
488 scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) { | |
489 DCHECK(IsImplThread()); | |
490 channel_impl_->PostFrameTimingEventsOnMain(std::move(composite_events), | |
491 std::move(main_frame_events)); | |
492 } | |
493 | |
494 void ProxyImpl::WillBeginImplFrame(const BeginFrameArgs& args) { | |
495 DCHECK(IsImplThread()); | |
496 layer_tree_host_impl_->WillBeginImplFrame(args); | |
497 if (last_processed_begin_main_frame_args_.IsValid()) { | |
498 // Last processed begin main frame args records the frame args that we sent | |
499 // to the main thread for the last frame that we've processed. If that is | |
500 // set, that means the current frame is one past the frame in which we've | |
501 // finished the processing. | |
502 layer_tree_host_impl_->RecordMainFrameTiming( | |
503 last_processed_begin_main_frame_args_, args); | |
504 last_processed_begin_main_frame_args_ = BeginFrameArgs(); | |
505 } | |
506 } | |
507 | |
508 void ProxyImpl::DidFinishImplFrame() { | |
509 DCHECK(IsImplThread()); | |
510 layer_tree_host_impl_->DidFinishImplFrame(); | |
511 } | |
512 | |
513 void ProxyImpl::ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) { | |
514 DCHECK(IsImplThread()); | |
515 unsigned int begin_frame_id = nextBeginFrameId++; | |
516 benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task( | |
517 benchmark_instrumentation::kSendBeginFrame, begin_frame_id); | |
518 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state( | |
519 new BeginMainFrameAndCommitState); | |
520 begin_main_frame_state->begin_frame_id = begin_frame_id; | |
521 begin_main_frame_state->begin_frame_args = args; | |
522 begin_main_frame_state->scroll_info = | |
523 layer_tree_host_impl_->ProcessScrollDeltas(); | |
524 begin_main_frame_state->memory_allocation_limit_bytes = | |
525 layer_tree_host_impl_->memory_allocation_limit_bytes(); | |
526 begin_main_frame_state->evicted_ui_resources = | |
527 layer_tree_host_impl_->EvictedUIResourcesExist(); | |
528 // TODO(vmpstr): This needs to be fixed if | |
529 // main_frame_before_activation_enabled is set, since we might run this code | |
530 // twice before recording a duration. crbug.com/469824 | |
531 last_begin_main_frame_args_ = begin_main_frame_state->begin_frame_args; | |
532 channel_impl_->BeginMainFrame(std::move(begin_main_frame_state)); | |
533 devtools_instrumentation::DidRequestMainThreadFrame(layer_tree_host_id_); | |
534 } | |
535 | |
536 DrawResult ProxyImpl::ScheduledActionDrawAndSwapIfPossible() { | |
537 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionDrawAndSwap"); | |
538 DCHECK(IsImplThread()); | |
539 | |
540 // SchedulerStateMachine::DidDrawIfPossibleCompleted isn't set up to | |
541 // handle DRAW_ABORTED_CANT_DRAW. Moreover, the scheduler should | |
542 // never generate this call when it can't draw. | |
543 DCHECK(layer_tree_host_impl_->CanDraw()); | |
544 | |
545 bool forced_draw = false; | |
546 return DrawAndSwapInternal(forced_draw); | |
547 } | |
548 | |
549 DrawResult ProxyImpl::ScheduledActionDrawAndSwapForced() { | |
550 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionDrawAndSwapForced"); | |
551 DCHECK(IsImplThread()); | |
552 bool forced_draw = true; | |
553 return DrawAndSwapInternal(forced_draw); | |
554 } | |
555 | |
556 void ProxyImpl::ScheduledActionAnimate() { | |
557 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionAnimate"); | |
558 DCHECK(IsImplThread()); | |
559 | |
560 layer_tree_host_impl_->Animate(); | |
561 } | |
562 | |
563 void ProxyImpl::ScheduledActionCommit() { | |
564 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionCommit"); | |
565 DCHECK(IsImplThread()); | |
566 DCHECK(IsMainThreadBlocked()); | |
567 DCHECK(commit_completion_event_); | |
568 | |
569 layer_tree_host_impl_->BeginCommit(); | |
570 blocked_main_commit().layer_tree_host->FinishCommitOnImplThread( | |
571 layer_tree_host_impl_.get()); | |
572 | |
573 // Remove the LayerTreeHost reference before the completion event is signaled | |
574 // and cleared. This is necessary since blocked_main_commit() allows access | |
575 // only while we have the completion event to ensure the main thread is | |
576 // blocked for a commit. | |
577 blocked_main_commit().layer_tree_host = nullptr; | |
578 | |
579 if (next_commit_waits_for_activation_) { | |
580 // For some layer types in impl-side painting, the commit is held until | |
581 // the sync tree is activated. It's also possible that the | |
582 // sync tree has already activated if there was no work to be done. | |
583 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD); | |
584 } else { | |
585 commit_completion_event_->Signal(); | |
586 commit_completion_event_ = nullptr; | |
587 } | |
588 | |
589 scheduler_->DidCommit(); | |
590 | |
591 // Delay this step until afer the main thread has been released as it's | |
592 // often a good bit of work to update the tree and prepare the new frame. | |
593 layer_tree_host_impl_->CommitComplete(); | |
594 | |
595 SetInputThrottledUntilCommitOnImpl(false); | |
596 | |
597 next_frame_is_newly_committed_frame_ = true; | |
598 } | |
599 | |
600 void ProxyImpl::ScheduledActionActivateSyncTree() { | |
601 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionActivateSyncTree"); | |
602 DCHECK(IsImplThread()); | |
603 layer_tree_host_impl_->ActivateSyncTree(); | |
604 } | |
605 | |
606 void ProxyImpl::ScheduledActionBeginOutputSurfaceCreation() { | |
607 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionBeginOutputSurfaceCreation"); | |
608 DCHECK(IsImplThread()); | |
609 channel_impl_->RequestNewOutputSurface(); | |
610 } | |
611 | |
612 void ProxyImpl::ScheduledActionPrepareTiles() { | |
613 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionPrepareTiles"); | |
614 DCHECK(IsImplThread()); | |
615 layer_tree_host_impl_->PrepareTiles(); | |
616 } | |
617 | |
618 void ProxyImpl::ScheduledActionInvalidateOutputSurface() { | |
619 TRACE_EVENT0("cc", "ProxyImpl::ScheduledActionInvalidateOutputSurface"); | |
620 DCHECK(IsImplThread()); | |
621 DCHECK(layer_tree_host_impl_->output_surface()); | |
622 layer_tree_host_impl_->output_surface()->Invalidate(); | |
623 } | |
624 | |
625 void ProxyImpl::SendBeginFramesToChildren(const BeginFrameArgs& args) { | |
626 NOTREACHED() << "Only used by SingleThreadProxy"; | |
627 } | |
628 | |
629 void ProxyImpl::SendBeginMainFrameNotExpectedSoon() { | |
630 DCHECK(IsImplThread()); | |
631 channel_impl_->BeginMainFrameNotExpectedSoon(); | |
632 } | |
633 | |
634 DrawResult ProxyImpl::DrawAndSwapInternal(bool forced_draw) { | |
635 TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap"); | |
636 | |
637 DCHECK(IsImplThread()); | |
638 DCHECK(layer_tree_host_impl_.get()); | |
639 | |
640 base::AutoReset<bool> mark_inside(&inside_draw_, true); | |
641 | |
642 if (layer_tree_host_impl_->pending_tree()) { | |
643 bool update_lcd_text = false; | |
644 layer_tree_host_impl_->pending_tree()->UpdateDrawProperties( | |
645 update_lcd_text); | |
646 } | |
647 | |
648 // This method is called on a forced draw, regardless of whether we are able | |
649 // to produce a frame, as the calling site on main thread is blocked until its | |
650 // request completes, and we signal completion here. If CanDraw() is false, we | |
651 // will indicate success=false to the caller, but we must still signal | |
652 // completion to avoid deadlock. | |
653 | |
654 // We guard PrepareToDraw() with CanDraw() because it always returns a valid | |
655 // frame, so can only be used when such a frame is possible. Since | |
656 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on | |
657 // CanDraw() as well. | |
658 | |
659 LayerTreeHostImpl::FrameData frame; | |
660 bool draw_frame = false; | |
661 | |
662 DrawResult result; | |
663 if (layer_tree_host_impl_->CanDraw()) { | |
664 result = layer_tree_host_impl_->PrepareToDraw(&frame); | |
665 draw_frame = forced_draw || result == DRAW_SUCCESS; | |
666 } else { | |
667 result = DRAW_ABORTED_CANT_DRAW; | |
668 } | |
669 | |
670 if (draw_frame) { | |
671 layer_tree_host_impl_->DrawLayers(&frame); | |
672 result = DRAW_SUCCESS; | |
673 } else { | |
674 DCHECK_NE(DRAW_SUCCESS, result); | |
675 } | |
676 layer_tree_host_impl_->DidDrawAllLayers(frame); | |
677 | |
678 bool start_ready_animations = draw_frame; | |
679 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations); | |
680 | |
681 if (draw_frame) | |
682 layer_tree_host_impl_->SwapBuffers(frame); | |
683 | |
684 // Tell the main thread that the the newly-commited frame was drawn. | |
685 if (next_frame_is_newly_committed_frame_) { | |
686 next_frame_is_newly_committed_frame_ = false; | |
687 channel_impl_->DidCommitAndDrawFrame(); | |
688 } | |
689 | |
690 DCHECK_NE(INVALID_RESULT, result); | |
691 return result; | |
692 } | |
693 | |
694 bool ProxyImpl::IsImplThread() const { | |
695 return task_runner_provider_->IsImplThread(); | |
696 } | |
697 | |
698 bool ProxyImpl::IsMainThreadBlocked() const { | |
699 return task_runner_provider_->IsMainThreadBlocked(); | |
700 } | |
701 | |
702 ProxyImpl::BlockedMainCommitOnly& ProxyImpl::blocked_main_commit() { | |
703 DCHECK(IsMainThreadBlocked() && commit_completion_event_); | |
704 return main_thread_blocked_commit_vars_unsafe_; | |
705 } | |
706 | |
707 } // namespace cc | |
OLD | NEW |