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

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

Issue 1417053005: cc: Split ThreadProxy into ProxyMain and ProxyImpl (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/trees/proxy_main.h"
6
7 #include <algorithm>
8 #include <string>
9
10 #include "base/auto_reset.h"
11 #include "base/bind.h"
12 #include "base/trace_event/trace_event.h"
13 #include "base/trace_event/trace_event_argument.h"
14 #include "base/trace_event/trace_event_synthetic_delay.h"
15 #include "cc/debug/benchmark_instrumentation.h"
16 #include "cc/debug/devtools_instrumentation.h"
17 #include "cc/input/input_handler.h"
18 #include "cc/input/top_controls_manager.h"
19 #include "cc/output/context_provider.h"
20 #include "cc/output/output_surface.h"
21 #include "cc/output/swap_promise.h"
22 #include "cc/quads/draw_quad.h"
23 #include "cc/scheduler/commit_earlyout_reason.h"
24 #include "cc/scheduler/compositor_timing_history.h"
25 #include "cc/scheduler/scheduler.h"
26 #include "cc/trees/blocking_task_runner.h"
27 #include "cc/trees/layer_tree_host.h"
28 #include "cc/trees/layer_tree_impl.h"
29 #include "cc/trees/scoped_abort_remaining_swap_promises.h"
30 #include "gpu/command_buffer/client/gles2_interface.h"
31
32 namespace cc {
33
34 scoped_ptr<ProxyMain> ProxyMain::Create(
35 LayerTreeHost* layer_tree_host,
36 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
37 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
38 scoped_ptr<BeginFrameSource> external_begin_frame_source) {
39 return make_scoped_ptr(new ProxyMain(layer_tree_host, main_task_runner,
40 impl_task_runner,
41 external_begin_frame_source.Pass()));
42 }
43
44 ProxyMain::ProxyMain(
45 LayerTreeHost* layer_tree_host,
46 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
47 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
48 scoped_ptr<BeginFrameSource> external_begin_frame_source)
49 : Proxy(main_task_runner, impl_task_runner),
50 layer_tree_host_(layer_tree_host),
51 layer_tree_host_id_(layer_tree_host->id()),
52 max_requested_pipeline_stage_(NO_PIPELINE_STAGE),
53 current_pipeline_stage_(NO_PIPELINE_STAGE),
54 final_pipeline_stage_(NO_PIPELINE_STAGE),
55 commit_waits_for_activation_(false),
56 started_(false),
57 prepare_tiles_pending_(false),
58 defer_commits_(false),
59 external_begin_frame_source_(external_begin_frame_source.Pass()),
60 weak_factory_(this) {
61 TRACE_EVENT0("cc", "ProxyMain::ProxyMain");
62 DCHECK(IsMainThread());
63 DCHECK(this->layer_tree_host_);
64 main_thread_weak_ptr_ = weak_factory_.GetWeakPtr();
65 }
66
67 ProxyMain::~ProxyMain() {
68 TRACE_EVENT0("cc", "ProxyMain::~ProxyMain");
69 DCHECK(IsMainThread());
70 DCHECK(!started_);
71 weak_factory_.InvalidateWeakPtrs();
72 }
73
74 void ProxyMain::SetChannel(scoped_ptr<ChannelMain> channel_main) {
75 DCHECK(!channel_main_);
76 channel_main_ = channel_main.Pass();
77 }
78
79 void ProxyMain::FinishAllRendering() {
80 DCHECK(Proxy::IsMainThread());
Wez 2015/11/10 01:41:51 nit: Why are some of these just IsMainThread, and
Khushal 2015/11/11 04:17:47 ThreadProxy implementation had that. Fixed.
81 DCHECK(!defer_commits_);
82
83 // Make sure all GL drawing is finished on the impl thread.
84 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
85 CompletionEvent completion;
86 channel_main_->FinishAllRenderingOnImpl(&completion);
87 completion.Wait();
88 }
89
90 bool ProxyMain::IsStarted() const {
91 DCHECK(Proxy::IsMainThread());
92 return started_;
93 }
94
95 bool ProxyMain::CommitToActiveTree() const {
96 // With ProxyMain, we use a pending tree and activate it once it's ready to
97 // draw to allow input to modify the active tree and draw during raster.
98 return false;
99 }
100
101 void ProxyMain::SetVisible(bool visible) {
102 TRACE_EVENT1("cc", "ProxyMain::SetVisible", "visible", visible);
103 channel_main_->SetVisibleOnImpl(visible);
104 }
105
106 void ProxyMain::SetThrottleFrameProduction(bool throttle) {
107 TRACE_EVENT1("cc", "ProxyMain::SetThrottleFrameProduction", "throttle",
108 throttle);
109 channel_main_->SetThrottleFrameProductionOnImpl(throttle);
110 }
111
112 void ProxyMain::DidLoseOutputSurface() {
113 TRACE_EVENT0("cc", "ProxyMain::DidLoseOutputSurface");
114 DCHECK(IsMainThread());
115 layer_tree_host_->DidLoseOutputSurface();
116 }
117
118 void ProxyMain::RequestNewOutputSurface() {
119 DCHECK(IsMainThread());
120 layer_tree_host_->RequestNewOutputSurface();
121 }
122
123 void ProxyMain::SetOutputSurface(OutputSurface* output_surface) {
124 channel_main_->InitializeOutputSurfaceOnImpl(output_surface);
125 }
126
127 void ProxyMain::ReleaseOutputSurface() {
128 DCHECK(IsMainThread());
129 DCHECK(layer_tree_host_->output_surface_lost());
130
131 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
132 CompletionEvent completion;
133 channel_main_->ReleaseOutputSurfaceOnImpl(&completion);
134 completion.Wait();
135 }
136
137 void ProxyMain::DidInitializeOutputSurface(
138 bool success,
139 const RendererCapabilities& capabilities) {
140 TRACE_EVENT0("cc", "ProxyMain::DidInitializeOutputSurface");
141 DCHECK(IsMainThread());
142
143 if (!success) {
144 layer_tree_host_->DidFailToInitializeOutputSurface();
145 return;
146 }
147 renderer_capabilities_main_thread_copy_ = capabilities;
148 layer_tree_host_->DidInitializeOutputSurface();
149 }
150
151 void ProxyMain::SetRendererCapabilitiesMainCopy(
152 const RendererCapabilities& capabilities) {
153 renderer_capabilities_main_thread_copy_ = capabilities;
154 }
155
156 bool ProxyMain::SendCommitRequestToImplThreadIfNeeded(
157 CommitPipelineStage required_stage) {
158 DCHECK(IsMainThread());
159 DCHECK_NE(NO_PIPELINE_STAGE, required_stage);
160 bool already_posted = max_requested_pipeline_stage_ != NO_PIPELINE_STAGE;
161 max_requested_pipeline_stage_ =
162 std::max(max_requested_pipeline_stage_, required_stage);
163 if (already_posted)
164 return false;
165 channel_main_->SetNeedsCommitOnImpl();
166 return true;
167 }
168
169 void ProxyMain::DidCompletePageScaleAnimation() {
170 DCHECK(IsMainThread());
171 layer_tree_host_->DidCompletePageScaleAnimation();
172 }
173
174 const RendererCapabilities& ProxyMain::GetRendererCapabilities() const {
175 DCHECK(IsMainThread());
176 DCHECK(!layer_tree_host_->output_surface_lost());
177 return renderer_capabilities_main_thread_copy_;
178 }
179
180 void ProxyMain::SetNeedsAnimate() {
181 DCHECK(IsMainThread());
182 if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE)) {
183 TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsAnimate",
184 TRACE_EVENT_SCOPE_THREAD);
185 }
186 }
187
188 void ProxyMain::SetNeedsUpdateLayers() {
189 DCHECK(IsMainThread());
190 // If we are currently animating, make sure we also update the layers.
191 if (current_pipeline_stage_ == ANIMATE_PIPELINE_STAGE) {
192 final_pipeline_stage_ =
193 std::max(final_pipeline_stage_, UPDATE_LAYERS_PIPELINE_STAGE);
194 return;
195 }
196 if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE)) {
197 TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsUpdateLayers",
198 TRACE_EVENT_SCOPE_THREAD);
199 }
200 }
201
202 void ProxyMain::SetNeedsCommit() {
203 DCHECK(IsMainThread());
204 // If we are currently animating, make sure we don't skip the commit. Note
205 // that requesting a commit during the layer update stage means we need to
206 // schedule another full commit.
207 if (current_pipeline_stage_ == ANIMATE_PIPELINE_STAGE) {
208 final_pipeline_stage_ =
209 std::max(final_pipeline_stage_, COMMIT_PIPELINE_STAGE);
210 return;
211 }
212 if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE)) {
213 TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsCommit",
214 TRACE_EVENT_SCOPE_THREAD);
215 }
216 }
217
218 void ProxyMain::SetNeedsRedraw(const gfx::Rect& damage_rect) {
219 TRACE_EVENT0("cc", "ProxyMain::SetNeedsRedraw");
220 DCHECK(IsMainThread());
221 channel_main_->SetNeedsRedrawOnImpl(damage_rect);
222 }
223
224 void ProxyMain::SetNextCommitWaitsForActivation() {
225 DCHECK(IsMainThread());
226 commit_waits_for_activation_ = true;
227 }
228
229 void ProxyMain::SetDeferCommits(bool defer_commits) {
230 DCHECK(IsMainThread());
231 if (defer_commits_ == defer_commits)
232 return;
233
234 defer_commits_ = defer_commits;
235 if (defer_commits_)
236 TRACE_EVENT_ASYNC_BEGIN0("cc", "ProxyMain::SetDeferCommits", this);
237 else
238 TRACE_EVENT_ASYNC_END0("cc", "ProxyMain::SetDeferCommits", this);
239
240 channel_main_->SetDeferCommitsOnImpl(defer_commits);
241 }
242
243 bool ProxyMain::CommitRequested() const {
244 DCHECK(IsMainThread());
245 // TODO(skyostil): Split this into something like CommitRequested() and
246 // CommitInProgress().
247 return current_pipeline_stage_ != NO_PIPELINE_STAGE ||
248 max_requested_pipeline_stage_ >= COMMIT_PIPELINE_STAGE;
249 }
250
251 bool ProxyMain::BeginMainFrameRequested() const {
252 DCHECK(IsMainThread());
253 return max_requested_pipeline_stage_ != NO_PIPELINE_STAGE;
254 }
255
256 void ProxyMain::MainThreadHasStoppedFlinging() {
257 DCHECK(IsMainThread());
258 channel_main_->MainThreadHasStoppedFlingingOnImpl();
259 }
260
261 void ProxyMain::NotifyInputThrottledUntilCommit() {
262 DCHECK(IsMainThread());
263 channel_main_->SetInputThrottledUntilCommitOnImpl(true);
264 }
265
266 void ProxyMain::Start() {
267 DCHECK(IsMainThread());
268 DCHECK(Proxy::HasImplThread());
269 DCHECK(channel_main_);
270
271 // Create LayerTreeHostImpl.
272 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
273 CompletionEvent completion;
274 channel_main_->InitializeImpl(&completion, layer_tree_host_,
275 external_begin_frame_source_.Pass());
276 completion.Wait();
277
278 started_ = true;
279 }
280
281 void ProxyMain::Stop() {
282 TRACE_EVENT0("cc", "ProxyMain::Stop");
283 DCHECK(IsMainThread());
284 DCHECK(started_);
285
286 // Synchronously finishes pending GL operations and deletes the impl.
287 // The two steps are done as separate post tasks, so that tasks posted
288 // by the GL implementation due to the Finish can be executed by the
289 // renderer before shutting it down.
290 {
291 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
292 CompletionEvent completion;
293 channel_main_->FinishGLOnImpl(&completion);
294 completion.Wait();
295 }
296 {
297 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
298
299 CompletionEvent completion;
300 channel_main_->CloseImpl(&completion);
301 completion.Wait();
302 }
303
304 layer_tree_host_ = nullptr;
305 started_ = false;
306 }
307
308 bool ProxyMain::SupportsImplScrolling() const {
309 return true;
310 }
311
312 void ProxyMain::BeginMainFrame(
313 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
314 benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
315 benchmark_instrumentation::kDoBeginFrame,
316 begin_main_frame_state->begin_frame_id);
317 TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
318 DCHECK(IsMainThread());
319 DCHECK_EQ(NO_PIPELINE_STAGE, current_pipeline_stage_);
320
321 if (defer_commits_) {
322 TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
323 TRACE_EVENT_SCOPE_THREAD);
324 channel_main_->BeginMainFrameAbortedOnImpl(
325 CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT);
326 return;
327 }
328
329 // If the commit finishes, LayerTreeHost will transfer its swap promises to
330 // LayerTreeImpl. The destructor of ScopedSwapPromiseChecker aborts the
331 // remaining swap promises.
332 ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
333
334 final_pipeline_stage_ = max_requested_pipeline_stage_;
335 max_requested_pipeline_stage_ = NO_PIPELINE_STAGE;
336
337 if (!layer_tree_host_->visible()) {
338 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
339 channel_main_->BeginMainFrameAbortedOnImpl(
340 CommitEarlyOutReason::ABORTED_NOT_VISIBLE);
341 return;
342 }
343
344 if (layer_tree_host_->output_surface_lost()) {
345 TRACE_EVENT_INSTANT0("cc", "EarlyOut_OutputSurfaceLost",
346 TRACE_EVENT_SCOPE_THREAD);
347 channel_main_->BeginMainFrameAbortedOnImpl(
348 CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST);
349 return;
350 }
351
352 current_pipeline_stage_ = ANIMATE_PIPELINE_STAGE;
353
354 layer_tree_host_->ApplyScrollAndScale(
355 begin_main_frame_state->scroll_info.get());
356
357 layer_tree_host_->WillBeginMainFrame();
358
359 layer_tree_host_->BeginMainFrame(begin_main_frame_state->begin_frame_args);
360 layer_tree_host_->AnimateLayers(
361 begin_main_frame_state->begin_frame_args.frame_time);
362
363 // Recreate all UI resources if there were evicted UI resources when the impl
364 // thread initiated the commit.
365 if (begin_main_frame_state->evicted_ui_resources)
366 layer_tree_host_->RecreateUIResources();
367
368 layer_tree_host_->RequestMainFrameUpdate();
369 TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
370
371 bool can_cancel_this_commit = final_pipeline_stage_ < COMMIT_PIPELINE_STAGE &&
372 !begin_main_frame_state->evicted_ui_resources;
373
374 current_pipeline_stage_ = UPDATE_LAYERS_PIPELINE_STAGE;
375 bool should_update_layers =
376 final_pipeline_stage_ >= UPDATE_LAYERS_PIPELINE_STAGE;
377 bool updated = should_update_layers && layer_tree_host_->UpdateLayers();
378
379 layer_tree_host_->WillCommit();
380 devtools_instrumentation::ScopedCommitTrace commit_task(
381 layer_tree_host_->id());
382
383 current_pipeline_stage_ = COMMIT_PIPELINE_STAGE;
384 if (!updated && can_cancel_this_commit) {
385 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
386 channel_main_->BeginMainFrameAbortedOnImpl(
387 CommitEarlyOutReason::FINISHED_NO_UPDATES);
388
389 // Although the commit is internally aborted, this is because it has been
390 // detected to be a no-op. From the perspective of an embedder, this commit
391 // went through, and input should no longer be throttled, etc.
392 current_pipeline_stage_ = NO_PIPELINE_STAGE;
393 layer_tree_host_->CommitComplete();
394 layer_tree_host_->DidBeginMainFrame();
395 layer_tree_host_->BreakSwapPromises(SwapPromise::COMMIT_NO_UPDATE);
396 return;
397 }
398
399 // Notify the impl thread that the main thread is ready to commit. This will
400 // begin the commit process, which is blocking from the main thread's
401 // point of view, but asynchronously performed on the impl thread,
402 // coordinated by the Scheduler.
403 {
404 TRACE_EVENT0("cc", "ProxyMain::BeginMainFrame::commit");
405
406 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
407
408 // This CapturePostTasks should be destroyed before CommitComplete() is
409 // called since that goes out to the embedder, and we want the embedder
410 // to receive its callbacks before that.
411 BlockingTaskRunner::CapturePostTasks blocked(
412 blocking_main_thread_task_runner());
413
414 bool hold_commit_for_activation = commit_waits_for_activation_;
415 commit_waits_for_activation_ = false;
416 CompletionEvent completion;
417 channel_main_->StartCommitOnImpl(&completion, layer_tree_host_,
418 hold_commit_for_activation);
419 completion.Wait();
420 }
421
422 current_pipeline_stage_ = NO_PIPELINE_STAGE;
423 layer_tree_host_->CommitComplete();
424 layer_tree_host_->DidBeginMainFrame();
425 }
426
427 void ProxyMain::BeginMainFrameNotExpectedSoon() {
428 TRACE_EVENT0("cc", "ProxyMain::BeginMainFrameNotExpectedSoon");
429 DCHECK(IsMainThread());
430 layer_tree_host_->BeginMainFrameNotExpectedSoon();
431 }
432
433 void ProxyMain::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) {
434 NOTREACHED() << "Only used by SingleProxyMain";
435 }
436
437 void ProxyMain::DidCommitAndDrawFrame() {
438 DCHECK(IsMainThread());
439 layer_tree_host_->DidCommitAndDrawFrame();
440 }
441
442 void ProxyMain::DidCompleteSwapBuffers() {
443 DCHECK(IsMainThread());
444 layer_tree_host_->DidCompleteSwapBuffers();
445 }
446
447 void ProxyMain::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
448 TRACE_EVENT0("cc", "ProxyMain::SetAnimationEvents");
449 DCHECK(IsMainThread());
450 layer_tree_host_->SetAnimationEvents(events.Pass());
451 }
452
453 bool ProxyMain::MainFrameWillHappenForTesting() {
454 DCHECK(IsMainThread());
455 bool main_frame_will_happen = false;
456 {
457 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
458 CompletionEvent completion;
459 channel_main_->MainFrameWillHappenOnImplForTesting(&completion,
460 &main_frame_will_happen);
461 completion.Wait();
462 }
463 return main_frame_will_happen;
464 }
465
466 void ProxyMain::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
467 NOTREACHED() << "Only used by SingleThreadProxy";
468 }
469
470 void ProxyMain::UpdateTopControlsState(TopControlsState constraints,
471 TopControlsState current,
472 bool animate) {
473 channel_main_->UpdateTopControlsStateOnImpl(constraints, current, animate);
474 }
475
476 void ProxyMain::PostFrameTimingEventsOnMain(
477 scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
478 scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
479 DCHECK(IsMainThread());
480 layer_tree_host_->RecordFrameTimingEvents(composite_events.Pass(),
481 main_frame_events.Pass());
482 }
483
484 base::WeakPtr<ProxyMain> ProxyMain::GetWeakPtr() {
485 return weak_factory_.GetWeakPtr();
486 }
487
488 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698