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

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

Powered by Google App Engine
This is Rietveld 408576698