blob: 263cd3ac544c3b79319f236d4b5a8f198a0669d7 [file] [log] [blame]
// 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/test/layer_tree_host_remote_for_testing.h"
#include "base/memory/ptr_util.h"
#include "cc/animation/animation_host.h"
#include "cc/blimp/compositor_proto_state.h"
#include "cc/blimp/compositor_state_deserializer.h"
#include "cc/blimp/remote_compositor_bridge.h"
#include "cc/layers/layer.h"
#include "cc/proto/compositor_message.pb.h"
#include "cc/test/fake_image_serialization_processor.h"
#include "cc/test/remote_client_layer_factory.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_in_process.h"
#include "cc/trees/mutator_host.h"
namespace cc {
class LayerTreeHostRemoteForTesting::RemoteCompositorBridgeImpl
: public RemoteCompositorBridge {
public:
RemoteCompositorBridgeImpl(
scoped_refptr<base::SingleThreadTaskRunner> compositor_main_task_runner)
: RemoteCompositorBridge(std::move(compositor_main_task_runner)) {}
~RemoteCompositorBridgeImpl() override = default;
void SetRemoteHost(LayerTreeHostRemoteForTesting* layer_tree_host_remote) {
DCHECK(layer_tree_host_remote);
layer_tree_host_remote_ = layer_tree_host_remote;
}
// RemoteCompositorBridge implementation.
void BindToClient(RemoteCompositorBridgeClient* client) override {
DCHECK(!client_);
client_ = client;
}
void ScheduleMainFrame() override {
layer_tree_host_remote_->RemoteHostNeedsMainFrame();
}
void ProcessCompositorStateUpdate(
std::unique_ptr<CompositorProtoState> compositor_proto_state) override {
layer_tree_host_remote_->ProcessRemoteCompositorUpdate(
std::move(compositor_proto_state));
}
private:
LayerTreeHostRemoteForTesting* layer_tree_host_remote_ = nullptr;
RemoteCompositorBridgeClient* client_ = nullptr;
};
class LayerTreeHostRemoteForTesting::LayerTreeHostInProcessClient
: public LayerTreeHostClient {
public:
LayerTreeHostInProcessClient(
LayerTreeHostRemoteForTesting* layer_tree_host_remote)
: layer_tree_host_remote_(layer_tree_host_remote) {}
~LayerTreeHostInProcessClient() override = default;
void WillBeginMainFrame() override {}
void BeginMainFrame(const BeginFrameArgs& args) override {
layer_tree_host_remote_->BeginRemoteMainFrame();
}
void BeginMainFrameNotExpectedSoon() override {}
void DidBeginMainFrame() override {}
void UpdateLayerTreeHost() override {}
void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
const gfx::Vector2dF& outer_delta,
const gfx::Vector2dF& elastic_overscroll_delta,
float page_scale,
float top_controls_delta) override {
layer_tree_host_remote_->compositor_state_deserializer_
->ApplyViewportDeltas(inner_delta, outer_delta,
elastic_overscroll_delta, page_scale,
top_controls_delta);
}
void RequestNewCompositorFrameSink() override {
layer_tree_host_remote_->client()->RequestNewCompositorFrameSink();
}
void DidInitializeCompositorFrameSink() override {
layer_tree_host_remote_->client()->DidInitializeCompositorFrameSink();
}
void DidFailToInitializeCompositorFrameSink() override {
layer_tree_host_remote_->client()->DidFailToInitializeCompositorFrameSink();
}
void WillCommit() override {}
void DidCommit() override {}
void DidCommitAndDrawFrame() override {
layer_tree_host_remote_->client()->DidCommitAndDrawFrame();
}
void DidReceiveCompositorFrameAck() override {
layer_tree_host_remote_->client()->DidReceiveCompositorFrameAck();
}
void DidCompletePageScaleAnimation() override {
NOTREACHED() << "The remote mode doesn't support sending animations";
}
private:
LayerTreeHostRemoteForTesting* layer_tree_host_remote_;
};
// static
std::unique_ptr<RemoteCompositorBridge>
LayerTreeHostRemoteForTesting::CreateRemoteCompositorBridge(
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
return base::MakeUnique<RemoteCompositorBridgeImpl>(
std::move(main_task_runner));
}
// static
std::unique_ptr<LayerTreeHostRemoteForTesting>
LayerTreeHostRemoteForTesting::Create(
LayerTreeHostClient* client,
MutatorHost* mutator_host,
LayerTreeSettings const* settings,
TaskGraphRunner* task_graph_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
std::unique_ptr<FakeImageSerializationProcessor>
image_serialization_processor =
base::MakeUnique<FakeImageSerializationProcessor>();
LayerTreeHostRemote::InitParams params;
params.client = client;
params.main_task_runner = main_task_runner;
params.mutator_host = mutator_host;
params.remote_compositor_bridge =
CreateRemoteCompositorBridge(main_task_runner);
params.engine_picture_cache =
image_serialization_processor->CreateEnginePictureCache();
params.settings = settings;
std::unique_ptr<LayerTreeHostRemoteForTesting> layer_tree_host =
base::WrapUnique(new LayerTreeHostRemoteForTesting(&params));
layer_tree_host->Initialize(task_graph_runner, main_task_runner,
impl_task_runner,
std::move(image_serialization_processor));
return layer_tree_host;
}
LayerTreeHostRemoteForTesting::LayerTreeHostRemoteForTesting(InitParams* params)
: LayerTreeHostRemote(params),
layer_tree_host_in_process_client_(
base::MakeUnique<LayerTreeHostInProcessClient>(this)) {}
LayerTreeHostRemoteForTesting::~LayerTreeHostRemoteForTesting() {
animation_host_->SetMutatorHostClient(nullptr);
compositor_state_deserializer_ = nullptr;
layer_tree_host_in_process_ = nullptr;
}
void LayerTreeHostRemoteForTesting::SetVisible(bool visible) {
LayerTreeHostRemote::SetVisible(visible);
// We need to tell the InProcessHost about visibility changes as well.
layer_tree_host_in_process_->SetVisible(visible);
}
void LayerTreeHostRemoteForTesting::SetCompositorFrameSink(
std::unique_ptr<CompositorFrameSink> compositor_frame_sink) {
// Pass through to the InProcessHost since this should be called only in
// response to a request made by it.
layer_tree_host_in_process_->SetCompositorFrameSink(
std::move(compositor_frame_sink));
}
std::unique_ptr<CompositorFrameSink>
LayerTreeHostRemoteForTesting::ReleaseCompositorFrameSink() {
// Pass through to the InProcessHost since that holds the CompositorFrameSink.
return layer_tree_host_in_process_->ReleaseCompositorFrameSink();
}
void LayerTreeHostRemoteForTesting::SetNeedsRedrawRect(
const gfx::Rect& damage_rect) {
// Draw requests pass through to the InProcessHost.
layer_tree_host_in_process_->SetNeedsRedrawRect(damage_rect);
}
void LayerTreeHostRemoteForTesting::SetNextCommitForcesRedraw() {
// Draw requests pass through to the InProcessHost.
layer_tree_host_in_process_->SetNextCommitForcesRedraw();
}
void LayerTreeHostRemoteForTesting::NotifyInputThrottledUntilCommit() {
// Pass through because the InProcessHost has the input handler.
layer_tree_host_in_process_->NotifyInputThrottledUntilCommit();
}
const base::WeakPtr<InputHandler>&
LayerTreeHostRemoteForTesting::GetInputHandler() const {
return layer_tree_host_in_process_->GetInputHandler();
}
void LayerTreeHostRemoteForTesting::Initialize(
TaskGraphRunner* task_graph_runner,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
std::unique_ptr<FakeImageSerializationProcessor>
image_serialization_processor) {
image_serialization_processor_ = std::move(image_serialization_processor);
RemoteCompositorBridgeImpl* remote_compositor_bridge_impl =
static_cast<RemoteCompositorBridgeImpl*>(remote_compositor_bridge());
remote_compositor_bridge_impl->SetRemoteHost(this);
animation_host_ = AnimationHost::CreateForTesting(ThreadInstance::MAIN);
layer_tree_host_in_process_ = CreateLayerTreeHostInProcess(
layer_tree_host_in_process_client_.get(), task_graph_runner,
GetSettings(), main_task_runner, impl_task_runner, animation_host_.get());
compositor_state_deserializer_ =
base::MakeUnique<CompositorStateDeserializer>(
layer_tree_host_in_process_.get(),
image_serialization_processor_->CreateClientPictureCache(), this);
// Override the LayerFactory since a lot of tests rely on the fact that Layers
// and LayerImpls have matching ids.
compositor_state_deserializer_->SetLayerFactoryForTesting(
base::MakeUnique<RemoteClientLayerFactory>());
// Override the TaskRunnerProvider since tests may rely on accessing the impl
// task runner using it.
SetTaskRunnerProviderForTesting(
TaskRunnerProvider::Create(main_task_runner, impl_task_runner));
}
std::unique_ptr<LayerTreeHostInProcess>
LayerTreeHostRemoteForTesting::CreateLayerTreeHostInProcess(
LayerTreeHostClient* client,
TaskGraphRunner* task_graph_runner,
const LayerTreeSettings& settings,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
MutatorHost* mutator_host) {
LayerTreeHostInProcess::InitParams params;
params.client = client;
params.task_graph_runner = task_graph_runner;
params.settings = &settings;
params.main_task_runner = main_task_runner;
params.mutator_host = mutator_host;
return LayerTreeHostInProcess::CreateThreaded(impl_task_runner, &params);
}
void LayerTreeHostRemoteForTesting::DidUpdateLocalState() {
client_state_dirty_ = true;
}
void LayerTreeHostRemoteForTesting::DispatchDrawAndSubmitCallbacks() {
// Don't dispatch callbacks right after the commit on the remote host. Since
// tests rely on CompositorFrames being swapped on the CompositorFrameSink,
// we wait for these callbacks from the LayerTreeHostInProcess.
}
void LayerTreeHostRemoteForTesting::RemoteHostNeedsMainFrame() {
layer_tree_host_in_process_->SetNeedsAnimate();
}
void LayerTreeHostRemoteForTesting::BeginRemoteMainFrame() {
// Send scroll/scale updates first if modified on the impl thread.
if (client_state_dirty_) {
client_state_dirty_ = false;
proto::ClientStateUpdate client_state_update;
compositor_state_deserializer_->PullClientStateUpdate(&client_state_update);
ApplyStateUpdateFromClient(client_state_update);
// Tell the host on the client that the updates were applied to the state
// on the remote host, in case the main frame on the remote host is aborted.
compositor_state_deserializer_->DidApplyStateUpdatesOnEngine();
}
BeginMainFrame();
}
void LayerTreeHostRemoteForTesting::ProcessRemoteCompositorUpdate(
std::unique_ptr<CompositorProtoState> compositor_proto_state) {
DCHECK(layer_tree_host_in_process_->CommitRequested());
// Deserialize the update from the remote host into client side LTH in
// process. This bypasses the network layer.
const proto::LayerTreeHost& layer_tree_host_proto =
compositor_proto_state->compositor_message->layer_tree_host();
compositor_state_deserializer_->DeserializeCompositorUpdate(
layer_tree_host_proto);
const proto::LayerUpdate& layer_updates =
compositor_proto_state->compositor_message->layer_tree_host()
.layer_updates();
for (int i = 0; i < layer_updates.layers_size(); ++i) {
int engine_layer_id = layer_updates.layers(i).id();
Layer* engine_layer = GetLayerTree()->LayerById(engine_layer_id);
Layer* client_layer =
compositor_state_deserializer_->GetLayerForEngineId(engine_layer_id);
// Copy test only layer data that are not serialized into network messages.
// So in test cases, layers on the client have the same states as their
// corresponding layers on the engine.
client_layer->SetForceRenderSurfaceForTesting(
engine_layer->force_render_surface_for_testing());
}
// The only case where the remote host would give a compositor update is if
// they wanted the main frame to go till the commit pipeline stage. So
// request one to make sure that the in process main frame also goes till
// the commit step.
layer_tree_host_in_process_->SetNeedsCommit();
}
} // namespace cc