// Copyright 2016 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/remote_channel_main.h" #include "base/memory/scoped_ptr.h" #include "cc/proto/base_conversions.h" #include "cc/proto/compositor_message.pb.h" #include "cc/proto/compositor_message_to_impl.pb.h" #include "cc/proto/compositor_message_to_main.pb.h" #include "cc/proto/gfx_conversions.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/proxy_main.h" namespace cc { scoped_ptr RemoteChannelMain::Create( RemoteProtoChannel* remote_proto_channel, ProxyMain* proxy_main, TaskRunnerProvider* task_runner_provider) { return make_scoped_ptr(new RemoteChannelMain(remote_proto_channel, proxy_main, task_runner_provider)); } RemoteChannelMain::RemoteChannelMain(RemoteProtoChannel* remote_proto_channel, ProxyMain* proxy_main, TaskRunnerProvider* task_runner_provider) : remote_proto_channel_(remote_proto_channel), proxy_main_(proxy_main), task_runner_provider_(task_runner_provider), initialized_(false), weak_factory_(this) { DCHECK(remote_proto_channel_); DCHECK(proxy_main_); DCHECK(task_runner_provider_); DCHECK(task_runner_provider_->IsMainThread()); remote_proto_channel_->SetProtoReceiver(this); } RemoteChannelMain::~RemoteChannelMain() { DCHECK(task_runner_provider_->IsMainThread()); DCHECK(!initialized_); remote_proto_channel_->SetProtoReceiver(nullptr); } void RemoteChannelMain::OnProtoReceived( scoped_ptr proto) { DCHECK(task_runner_provider_->IsMainThread()); DCHECK(proto->has_to_main()); HandleProto(proto->to_main()); } void RemoteChannelMain::UpdateTopControlsStateOnImpl( TopControlsState constraints, TopControlsState current, bool animate) {} void RemoteChannelMain::InitializeOutputSurfaceOnImpl( OutputSurface* output_surface) { NOTREACHED() << "Should not be called on the server LayerTreeHost"; } void RemoteChannelMain::MainThreadHasStoppedFlingingOnImpl() { proto::CompositorMessage proto; proto::CompositorMessageToImpl* to_impl_proto = proto.mutable_to_impl(); to_impl_proto->set_message_type( proto::CompositorMessageToImpl::MAIN_THREAD_HAS_STOPPED_FLINGING_ON_IMPL); SendMessageProto(proto); } void RemoteChannelMain::SetInputThrottledUntilCommitOnImpl(bool is_throttled) {} void RemoteChannelMain::SetDeferCommitsOnImpl(bool defer_commits) { proto::CompositorMessage proto; proto::CompositorMessageToImpl* to_impl_proto = proto.mutable_to_impl(); to_impl_proto->set_message_type( proto::CompositorMessageToImpl::SET_DEFER_COMMITS); proto::SetDeferCommits* defer_commits_message = to_impl_proto->mutable_defer_commits_message(); defer_commits_message->set_defer_commits(defer_commits); SendMessageProto(proto); } void RemoteChannelMain::FinishAllRenderingOnImpl(CompletionEvent* completion) { completion->Signal(); } void RemoteChannelMain::SetVisibleOnImpl(bool visible) { NOTIMPLEMENTED() << "Visibility is not controlled by the server"; } void RemoteChannelMain::ReleaseOutputSurfaceOnImpl( CompletionEvent* completion) { NOTREACHED() << "Should not be called on the server LayerTreeHost"; completion->Signal(); } void RemoteChannelMain::MainFrameWillHappenOnImplForTesting( CompletionEvent* completion, bool* main_frame_will_happen) { // For the LayerTreeTests in remote mode, LayerTreeTest directly calls // RemoteChannelImpl::MainFrameWillHappenForTesting and avoids adding a // message type for tests to the compositor protocol. NOTREACHED(); } void RemoteChannelMain::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) { proto::CompositorMessage proto; proto::CompositorMessageToImpl* to_impl_proto = proto.mutable_to_impl(); to_impl_proto->set_message_type( proto::CompositorMessageToImpl::SET_NEEDS_REDRAW); proto::SetNeedsRedraw* set_needs_redraw_message = to_impl_proto->mutable_set_needs_redraw_message(); RectToProto(damage_rect, set_needs_redraw_message->mutable_damaged_rect()); SendMessageProto(proto); // The client will not inform us when the frame buffers are swapped. MainThreadTaskRunner()->PostTask( FROM_HERE, base::Bind(&RemoteChannelMain::DidCompleteSwapBuffers, weak_factory_.GetWeakPtr())); } void RemoteChannelMain::SetNeedsCommitOnImpl() { proto::CompositorMessage proto; proto::CompositorMessageToImpl* to_impl_proto = proto.mutable_to_impl(); to_impl_proto->set_message_type( proto::CompositorMessageToImpl::SET_NEEDS_COMMIT); SendMessageProto(proto); } void RemoteChannelMain::BeginMainFrameAbortedOnImpl( CommitEarlyOutReason reason, base::TimeTicks main_thread_start_time) { proto::CompositorMessage proto; proto::CompositorMessageToImpl* to_impl_proto = proto.mutable_to_impl(); to_impl_proto->set_message_type( proto::CompositorMessageToImpl::BEGIN_MAIN_FRAME_ABORTED); proto::BeginMainFrameAborted* begin_main_frame_aborted_message = to_impl_proto->mutable_begin_main_frame_aborted_message(); CommitEarlyOutReasonToProtobuf( reason, begin_main_frame_aborted_message->mutable_reason()); SendMessageProto(proto); } void RemoteChannelMain::StartCommitOnImpl( CompletionEvent* completion, LayerTreeHost* layer_tree_host, base::TimeTicks main_thread_start_time, bool hold_commit_for_activation) { proto::CompositorMessage proto; proto::CompositorMessageToImpl* to_impl_proto = proto.mutable_to_impl(); to_impl_proto->set_message_type(proto::CompositorMessageToImpl::START_COMMIT); proto::StartCommit* start_commit_message = to_impl_proto->mutable_start_commit_message(); layer_tree_host->ToProtobufForCommit( start_commit_message->mutable_layer_tree_host()); SendMessageProto(proto); // In order to avoid incurring the overhead for the client to send us a // message for when a frame to be committed is drawn we inform the embedder // that the draw was successful immediately after sending the commit message. // Since the compositing state may be used by the embedder to throttle // commit/draw requests, it is better to allow them to propagate rather than // incurring a round-trip to get Acks for draw from the client for each frame. // This is done as a separate PostTask to ensure that these calls run after // LayerTreeHostClient::DidCommit and stay consistent with the // behaviour in the threaded compositor. MainThreadTaskRunner()->PostTask( FROM_HERE, base::Bind(&RemoteChannelMain::DidCommitAndDrawFrame, weak_factory_.GetWeakPtr())); completion->Signal(); } void RemoteChannelMain::SynchronouslyInitializeImpl( LayerTreeHost* layer_tree_host, scoped_ptr external_begin_frame_source) { DCHECK(!initialized_); proto::CompositorMessage proto; proto::CompositorMessageToImpl* to_impl_proto = proto.mutable_to_impl(); to_impl_proto->set_message_type( proto::CompositorMessageToImpl::INITIALIZE_IMPL); proto::InitializeImpl* initialize_impl_proto = to_impl_proto->mutable_initialize_impl_message(); proto::LayerTreeSettings* settings_proto = initialize_impl_proto->mutable_layer_tree_settings(); layer_tree_host->settings().ToProtobuf(settings_proto); SendMessageProto(proto); initialized_ = true; } void RemoteChannelMain::SynchronouslyCloseImpl() { DCHECK(initialized_); proto::CompositorMessage proto; proto::CompositorMessageToImpl* to_impl_proto = proto.mutable_to_impl(); to_impl_proto->set_message_type(proto::CompositorMessageToImpl::CLOSE_IMPL); SendMessageProto(proto); initialized_ = false; } void RemoteChannelMain::SendMessageProto( const proto::CompositorMessage& proto) { remote_proto_channel_->SendCompositorProto(proto); } void RemoteChannelMain::HandleProto( const proto::CompositorMessageToMain& proto) { DCHECK(proto.has_message_type()); switch (proto.message_type()) { case proto::CompositorMessageToMain::UNKNOWN: NOTIMPLEMENTED() << "Ignoring message proto of unknown type"; break; case proto::CompositorMessageToMain::BEGIN_MAIN_FRAME: { const proto::BeginMainFrame& begin_main_frame_message = proto.begin_main_frame_message(); scoped_ptr begin_main_frame_state; begin_main_frame_state.reset(new BeginMainFrameAndCommitState); begin_main_frame_state->FromProtobuf( begin_main_frame_message.begin_main_frame_state()); proxy_main_->BeginMainFrame(std::move(begin_main_frame_state)); } break; } } void RemoteChannelMain::DidCommitAndDrawFrame() { proxy_main_->DidCommitAndDrawFrame(); DidCompleteSwapBuffers(); } void RemoteChannelMain::DidCompleteSwapBuffers() { proxy_main_->DidCompleteSwapBuffers(); } base::SingleThreadTaskRunner* RemoteChannelMain::MainThreadTaskRunner() const { return task_runner_provider_->MainThreadTaskRunner(); } } // namespace cc