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

Unified 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: Addressing brianderson@'s comments, remove benchmark name change. 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/trees/proxy_main.h ('k') | cc/trees/thread_proxy.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/trees/proxy_main.cc
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
new file mode 100644
index 0000000000000000000000000000000000000000..dd5ac1afe5e6784188386ddec36905c46af43d1d
--- /dev/null
+++ b/cc/trees/proxy_main.cc
@@ -0,0 +1,465 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/proxy_main.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_argument.h"
+#include "base/trace_event/trace_event_synthetic_delay.h"
+#include "cc/debug/benchmark_instrumentation.h"
+#include "cc/debug/devtools_instrumentation.h"
+#include "cc/output/output_surface.h"
+#include "cc/output/swap_promise.h"
+#include "cc/trees/blocking_task_runner.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/scoped_abort_remaining_swap_promises.h"
+#include "cc/trees/threaded_channel.h"
+
+namespace cc {
+
+scoped_ptr<ProxyMain> ProxyMain::CreateThreaded(
+ LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source) {
+ scoped_ptr<ProxyMain> proxy_main(
+ new ProxyMain(layer_tree_host, task_runner_provider,
+ std::move(external_begin_frame_source)));
+ proxy_main->SetChannel(
+ ThreadedChannel::Create(proxy_main.get(), task_runner_provider));
+ return proxy_main;
+}
+
+ProxyMain::ProxyMain(LayerTreeHost* layer_tree_host,
+ TaskRunnerProvider* task_runner_provider,
+ scoped_ptr<BeginFrameSource> external_begin_frame_source)
+ : layer_tree_host_(layer_tree_host),
+ task_runner_provider_(task_runner_provider),
+ layer_tree_host_id_(layer_tree_host->id()),
+ max_requested_pipeline_stage_(NO_PIPELINE_STAGE),
+ current_pipeline_stage_(NO_PIPELINE_STAGE),
+ final_pipeline_stage_(NO_PIPELINE_STAGE),
+ commit_waits_for_activation_(false),
+ started_(false),
+ defer_commits_(false),
+ external_begin_frame_source_(std::move(external_begin_frame_source)) {
+ TRACE_EVENT0("cc", "ProxyMain::ProxyMain");
+ DCHECK(task_runner_provider_);
+ DCHECK(IsMainThread());
+ DCHECK(!layer_tree_host_->settings().use_external_begin_frame_source ||
+ external_begin_frame_source_);
+}
+
+ProxyMain::~ProxyMain() {
+ TRACE_EVENT0("cc", "ProxyMain::~ProxyMain");
+ DCHECK(IsMainThread());
+ DCHECK(!started_);
+}
+
+void ProxyMain::SetChannel(scoped_ptr<ChannelMain> channel_main) {
+ DCHECK(!channel_main_);
+ channel_main_ = std::move(channel_main);
+}
+
+void ProxyMain::DidCompleteSwapBuffers() {
+ DCHECK(IsMainThread());
+ layer_tree_host_->DidCompleteSwapBuffers();
+}
+
+void ProxyMain::SetRendererCapabilities(
+ const RendererCapabilities& capabilities) {
+ DCHECK(IsMainThread());
+ renderer_capabilities_ = capabilities;
+}
+
+void ProxyMain::BeginMainFrameNotExpectedSoon() {
+ TRACE_EVENT0("cc", "ProxyMain::BeginMainFrameNotExpectedSoon");
+ DCHECK(IsMainThread());
+ layer_tree_host_->BeginMainFrameNotExpectedSoon();
+}
+
+void ProxyMain::DidCommitAndDrawFrame() {
+ DCHECK(IsMainThread());
+ layer_tree_host_->DidCommitAndDrawFrame();
+}
+
+void ProxyMain::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
+ TRACE_EVENT0("cc", "ProxyMain::SetAnimationEvents");
+ DCHECK(IsMainThread());
+ layer_tree_host_->SetAnimationEvents(std::move(events));
+}
+
+void ProxyMain::DidLoseOutputSurface() {
+ TRACE_EVENT0("cc", "ProxyMain::DidLoseOutputSurface");
+ DCHECK(IsMainThread());
+ layer_tree_host_->DidLoseOutputSurface();
+}
+
+void ProxyMain::RequestNewOutputSurface() {
+ DCHECK(IsMainThread());
+ layer_tree_host_->RequestNewOutputSurface();
+}
+
+void ProxyMain::DidInitializeOutputSurface(
+ bool success,
+ const RendererCapabilities& capabilities) {
+ TRACE_EVENT0("cc", "ProxyMain::DidInitializeOutputSurface");
+ DCHECK(IsMainThread());
+
+ if (!success) {
+ layer_tree_host_->DidFailToInitializeOutputSurface();
+ return;
+ }
+ renderer_capabilities_ = capabilities;
+ layer_tree_host_->DidInitializeOutputSurface();
+}
+
+void ProxyMain::DidCompletePageScaleAnimation() {
+ DCHECK(IsMainThread());
+ layer_tree_host_->DidCompletePageScaleAnimation();
+}
+
+void ProxyMain::PostFrameTimingEventsOnMain(
+ scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
+ scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
+ DCHECK(IsMainThread());
+ layer_tree_host_->RecordFrameTimingEvents(std::move(composite_events),
+ std::move(main_frame_events));
+}
+
+void ProxyMain::BeginMainFrame(
+ scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
+ benchmark_instrumentation::ScopedBeginFrameTask begin_frame_task(
+ benchmark_instrumentation::kDoBeginFrame,
+ begin_main_frame_state->begin_frame_id);
+
+ base::TimeTicks begin_main_frame_start_time = base::TimeTicks::Now();
+
+ TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
+ DCHECK(IsMainThread());
+ DCHECK_EQ(NO_PIPELINE_STAGE, current_pipeline_stage_);
+
+ if (defer_commits_) {
+ TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
+ TRACE_EVENT_SCOPE_THREAD);
+ channel_main_->BeginMainFrameAbortedOnImpl(
+ CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT,
+ begin_main_frame_start_time);
+ return;
+ }
+
+ // If the commit finishes, LayerTreeHost will transfer its swap promises to
+ // LayerTreeImpl. The destructor of ScopedSwapPromiseChecker aborts the
+ // remaining swap promises.
+ ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
+
+ final_pipeline_stage_ = max_requested_pipeline_stage_;
+ max_requested_pipeline_stage_ = NO_PIPELINE_STAGE;
+
+ if (!layer_tree_host_->visible()) {
+ TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
+ channel_main_->BeginMainFrameAbortedOnImpl(
+ CommitEarlyOutReason::ABORTED_NOT_VISIBLE, begin_main_frame_start_time);
+ return;
+ }
+
+ if (layer_tree_host_->output_surface_lost()) {
+ TRACE_EVENT_INSTANT0("cc", "EarlyOut_OutputSurfaceLost",
+ TRACE_EVENT_SCOPE_THREAD);
+ channel_main_->BeginMainFrameAbortedOnImpl(
+ CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST,
+ begin_main_frame_start_time);
+ return;
+ }
+
+ current_pipeline_stage_ = ANIMATE_PIPELINE_STAGE;
+
+ layer_tree_host_->ApplyScrollAndScale(
+ begin_main_frame_state->scroll_info.get());
+
+ layer_tree_host_->WillBeginMainFrame();
+
+ layer_tree_host_->BeginMainFrame(begin_main_frame_state->begin_frame_args);
+ layer_tree_host_->AnimateLayers(
+ begin_main_frame_state->begin_frame_args.frame_time);
+
+ // Recreate all UI resources if there were evicted UI resources when the impl
+ // thread initiated the commit.
+ if (begin_main_frame_state->evicted_ui_resources)
+ layer_tree_host_->RecreateUIResources();
+
+ layer_tree_host_->RequestMainFrameUpdate();
+ TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
+
+ bool can_cancel_this_commit = final_pipeline_stage_ < COMMIT_PIPELINE_STAGE &&
+ !begin_main_frame_state->evicted_ui_resources;
+
+ current_pipeline_stage_ = UPDATE_LAYERS_PIPELINE_STAGE;
+ bool should_update_layers =
+ final_pipeline_stage_ >= UPDATE_LAYERS_PIPELINE_STAGE;
+ bool updated = should_update_layers && layer_tree_host_->UpdateLayers();
+
+ layer_tree_host_->WillCommit();
+ devtools_instrumentation::ScopedCommitTrace commit_task(
+ layer_tree_host_->id());
+
+ current_pipeline_stage_ = COMMIT_PIPELINE_STAGE;
+ if (!updated && can_cancel_this_commit) {
+ TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
+ channel_main_->BeginMainFrameAbortedOnImpl(
+ CommitEarlyOutReason::FINISHED_NO_UPDATES, begin_main_frame_start_time);
+
+ // Although the commit is internally aborted, this is because it has been
+ // detected to be a no-op. From the perspective of an embedder, this commit
+ // went through, and input should no longer be throttled, etc.
+ current_pipeline_stage_ = NO_PIPELINE_STAGE;
+ layer_tree_host_->CommitComplete();
+ layer_tree_host_->DidBeginMainFrame();
+ layer_tree_host_->BreakSwapPromises(SwapPromise::COMMIT_NO_UPDATE);
+ return;
+ }
+
+ // Notify the impl thread that the main thread is ready to commit. This will
+ // begin the commit process, which is blocking from the main thread's
+ // point of view, but asynchronously performed on the impl thread,
+ // coordinated by the Scheduler.
+ {
+ TRACE_EVENT0("cc", "ProxyMain::BeginMainFrame::commit");
+
+ DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+
+ // This CapturePostTasks should be destroyed before CommitComplete() is
+ // called since that goes out to the embedder, and we want the embedder
+ // to receive its callbacks before that.
+ BlockingTaskRunner::CapturePostTasks blocked(
+ task_runner_provider_->blocking_main_thread_task_runner());
+
+ bool hold_commit_for_activation = commit_waits_for_activation_;
+ commit_waits_for_activation_ = false;
+ CompletionEvent completion;
+ channel_main_->StartCommitOnImpl(&completion, layer_tree_host_,
+ begin_main_frame_start_time,
+ hold_commit_for_activation);
+ completion.Wait();
+ }
+
+ current_pipeline_stage_ = NO_PIPELINE_STAGE;
+ layer_tree_host_->CommitComplete();
+ layer_tree_host_->DidBeginMainFrame();
+}
+
+void ProxyMain::FinishAllRendering() {
+ DCHECK(IsMainThread());
+ DCHECK(!defer_commits_);
+
+ // Make sure all GL drawing is finished on the impl thread.
+ DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+ CompletionEvent completion;
+ channel_main_->FinishAllRenderingOnImpl(&completion);
+ completion.Wait();
+}
+
+bool ProxyMain::IsStarted() const {
+ DCHECK(IsMainThread());
+ return started_;
+}
+
+bool ProxyMain::CommitToActiveTree() const {
+ // With ProxyMain, we use a pending tree and activate it once it's ready to
+ // draw to allow input to modify the active tree and draw during raster.
+ return false;
+}
+
+void ProxyMain::SetOutputSurface(OutputSurface* output_surface) {
+ channel_main_->InitializeOutputSurfaceOnImpl(output_surface);
+}
+
+void ProxyMain::SetVisible(bool visible) {
+ TRACE_EVENT1("cc", "ProxyMain::SetVisible", "visible", visible);
+ channel_main_->SetVisibleOnImpl(visible);
+}
+
+void ProxyMain::SetThrottleFrameProduction(bool throttle) {
+ TRACE_EVENT1("cc", "ProxyMain::SetThrottleFrameProduction", "throttle",
+ throttle);
+ channel_main_->SetThrottleFrameProductionOnImpl(throttle);
+}
+
+const RendererCapabilities& ProxyMain::GetRendererCapabilities() const {
+ DCHECK(IsMainThread());
+ DCHECK(!layer_tree_host_->output_surface_lost());
+ return renderer_capabilities_;
+}
+
+void ProxyMain::SetNeedsAnimate() {
+ DCHECK(IsMainThread());
+ if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE)) {
+ TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsAnimate",
+ TRACE_EVENT_SCOPE_THREAD);
+ }
+}
+
+void ProxyMain::SetNeedsUpdateLayers() {
+ DCHECK(IsMainThread());
+ // If we are currently animating, make sure we also update the layers.
+ if (current_pipeline_stage_ == ANIMATE_PIPELINE_STAGE) {
+ final_pipeline_stage_ =
+ std::max(final_pipeline_stage_, UPDATE_LAYERS_PIPELINE_STAGE);
+ return;
+ }
+ if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE)) {
+ TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsUpdateLayers",
+ TRACE_EVENT_SCOPE_THREAD);
+ }
+}
+
+void ProxyMain::SetNeedsCommit() {
+ DCHECK(IsMainThread());
+ // If we are currently animating, make sure we don't skip the commit. Note
+ // that requesting a commit during the layer update stage means we need to
+ // schedule another full commit.
+ if (current_pipeline_stage_ == ANIMATE_PIPELINE_STAGE) {
+ final_pipeline_stage_ =
+ std::max(final_pipeline_stage_, COMMIT_PIPELINE_STAGE);
+ return;
+ }
+ if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE)) {
+ TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsCommit",
+ TRACE_EVENT_SCOPE_THREAD);
+ }
+}
+
+void ProxyMain::SetNeedsRedraw(const gfx::Rect& damage_rect) {
+ TRACE_EVENT0("cc", "ProxyMain::SetNeedsRedraw");
+ DCHECK(IsMainThread());
+ channel_main_->SetNeedsRedrawOnImpl(damage_rect);
+}
+
+void ProxyMain::SetNextCommitWaitsForActivation() {
+ DCHECK(IsMainThread());
+ commit_waits_for_activation_ = true;
+}
+
+void ProxyMain::NotifyInputThrottledUntilCommit() {
+ DCHECK(IsMainThread());
+ channel_main_->SetInputThrottledUntilCommitOnImpl(true);
+}
+
+void ProxyMain::SetDeferCommits(bool defer_commits) {
+ DCHECK(IsMainThread());
+ if (defer_commits_ == defer_commits)
+ return;
+
+ defer_commits_ = defer_commits;
+ if (defer_commits_)
+ TRACE_EVENT_ASYNC_BEGIN0("cc", "ProxyMain::SetDeferCommits", this);
+ else
+ TRACE_EVENT_ASYNC_END0("cc", "ProxyMain::SetDeferCommits", this);
+
+ channel_main_->SetDeferCommitsOnImpl(defer_commits);
+}
+
+bool ProxyMain::CommitRequested() const {
+ DCHECK(IsMainThread());
+ // TODO(skyostil): Split this into something like CommitRequested() and
+ // CommitInProgress().
+ return current_pipeline_stage_ != NO_PIPELINE_STAGE ||
+ max_requested_pipeline_stage_ >= COMMIT_PIPELINE_STAGE;
+}
+
+bool ProxyMain::BeginMainFrameRequested() const {
+ DCHECK(IsMainThread());
+ return max_requested_pipeline_stage_ != NO_PIPELINE_STAGE;
+}
+
+void ProxyMain::MainThreadHasStoppedFlinging() {
+ DCHECK(IsMainThread());
+ channel_main_->MainThreadHasStoppedFlingingOnImpl();
+}
+
+void ProxyMain::Start() {
+ DCHECK(IsMainThread());
+ DCHECK(task_runner_provider_->HasImplThread());
+ DCHECK(channel_main_);
+
+ // Create LayerTreeHostImpl.
+ channel_main_->SynchronouslyInitializeImpl(
+ layer_tree_host_, std::move(external_begin_frame_source_));
+
+ started_ = true;
+}
+
+void ProxyMain::Stop() {
+ TRACE_EVENT0("cc", "ProxyMain::Stop");
+ DCHECK(IsMainThread());
+ DCHECK(started_);
+
+ channel_main_->SynchronouslyCloseImpl();
+
+ layer_tree_host_ = nullptr;
+ started_ = false;
+}
+
+bool ProxyMain::SupportsImplScrolling() const {
+ return true;
+}
+
+bool ProxyMain::MainFrameWillHappenForTesting() {
+ DCHECK(IsMainThread());
+ bool main_frame_will_happen = false;
+ {
+ DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+ CompletionEvent completion;
+ channel_main_->MainFrameWillHappenOnImplForTesting(&completion,
+ &main_frame_will_happen);
+ completion.Wait();
+ }
+ return main_frame_will_happen;
+}
+
+void ProxyMain::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
+ NOTREACHED() << "Only used by SingleThreadProxy";
+}
+
+void ProxyMain::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) {
+ NOTREACHED() << "Only used by SingleProxyMain";
+}
+
+void ProxyMain::ReleaseOutputSurface() {
+ DCHECK(IsMainThread());
+ DCHECK(layer_tree_host_->output_surface_lost());
+
+ DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
+ CompletionEvent completion;
+ channel_main_->ReleaseOutputSurfaceOnImpl(&completion);
+ completion.Wait();
+}
+
+void ProxyMain::UpdateTopControlsState(TopControlsState constraints,
+ TopControlsState current,
+ bool animate) {
+ DCHECK(IsMainThread());
+ channel_main_->UpdateTopControlsStateOnImpl(constraints, current, animate);
+}
+
+bool ProxyMain::SendCommitRequestToImplThreadIfNeeded(
+ CommitPipelineStage required_stage) {
+ DCHECK(IsMainThread());
+ DCHECK_NE(NO_PIPELINE_STAGE, required_stage);
+ bool already_posted = max_requested_pipeline_stage_ != NO_PIPELINE_STAGE;
+ max_requested_pipeline_stage_ =
+ std::max(max_requested_pipeline_stage_, required_stage);
+ if (already_posted)
+ return false;
+ channel_main_->SetNeedsCommitOnImpl();
+ return true;
+}
+
+bool ProxyMain::IsMainThread() const {
+ return task_runner_provider_->IsMainThread();
+}
+
+} // namespace cc
« no previous file with comments | « cc/trees/proxy_main.h ('k') | cc/trees/thread_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698