blob: 4ddf839af7ecacd67a923d731eb5bc9d11208db4 [file] [log] [blame]
// Copyright 2017 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 "components/viz/client/client_layer_tree_frame_sink.h"
#include <utility>
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/trace_event/trace_event.h"
#include "cc/trees/layer_tree_frame_sink_client.h"
#include "components/viz/client/hit_test_data_provider.h"
#include "components/viz/client/local_surface_id_provider.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/resources/shared_bitmap_manager.h"
namespace viz {
ClientLayerTreeFrameSink::InitParams::InitParams() = default;
ClientLayerTreeFrameSink::InitParams::~InitParams() = default;
ClientLayerTreeFrameSink::UnboundMessagePipes::UnboundMessagePipes() = default;
ClientLayerTreeFrameSink::UnboundMessagePipes::~UnboundMessagePipes() = default;
bool ClientLayerTreeFrameSink::UnboundMessagePipes::HasUnbound() const {
return client_request.is_pending() &&
(compositor_frame_sink_info.is_valid() ^
compositor_frame_sink_associated_info.is_valid());
}
ClientLayerTreeFrameSink::UnboundMessagePipes::UnboundMessagePipes(
UnboundMessagePipes&& other) = default;
ClientLayerTreeFrameSink::ClientLayerTreeFrameSink(
scoped_refptr<ContextProvider> context_provider,
scoped_refptr<ContextProvider> worker_context_provider,
InitParams* params)
: cc::LayerTreeFrameSink(std::move(context_provider),
std::move(worker_context_provider),
params->gpu_memory_buffer_manager,
params->shared_bitmap_manager),
hit_test_data_provider_(std::move(params->hit_test_data_provider)),
local_surface_id_provider_(std::move(params->local_surface_id_provider)),
synthetic_begin_frame_source_(
std::move(params->synthetic_begin_frame_source)),
pipes_(std::move(params->pipes)),
client_binding_(this),
enable_surface_synchronization_(params->enable_surface_synchronization),
weak_factory_(this) {
DETACH_FROM_THREAD(thread_checker_);
}
ClientLayerTreeFrameSink::ClientLayerTreeFrameSink(
scoped_refptr<VulkanContextProvider> vulkan_context_provider,
InitParams* params)
: cc::LayerTreeFrameSink(std::move(vulkan_context_provider)),
hit_test_data_provider_(std::move(params->hit_test_data_provider)),
local_surface_id_provider_(std::move(params->local_surface_id_provider)),
synthetic_begin_frame_source_(
std::move(params->synthetic_begin_frame_source)),
pipes_(std::move(params->pipes)),
client_binding_(this),
enable_surface_synchronization_(params->enable_surface_synchronization),
weak_factory_(this) {
DETACH_FROM_THREAD(thread_checker_);
}
ClientLayerTreeFrameSink::~ClientLayerTreeFrameSink() {}
base::WeakPtr<ClientLayerTreeFrameSink> ClientLayerTreeFrameSink::GetWeakPtr() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return weak_factory_.GetWeakPtr();
}
bool ClientLayerTreeFrameSink::BindToClient(
cc::LayerTreeFrameSinkClient* client) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!cc::LayerTreeFrameSink::BindToClient(client))
return false;
DCHECK(pipes_.HasUnbound());
if (pipes_.compositor_frame_sink_info.is_valid()) {
compositor_frame_sink_.Bind(std::move(pipes_.compositor_frame_sink_info));
compositor_frame_sink_.set_connection_error_with_reason_handler(
base::Bind(ClientLayerTreeFrameSink::OnMojoConnectionError));
compositor_frame_sink_ptr_ = compositor_frame_sink_.get();
} else if (pipes_.compositor_frame_sink_associated_info.is_valid()) {
compositor_frame_sink_associated_.Bind(
std::move(pipes_.compositor_frame_sink_associated_info));
compositor_frame_sink_associated_.set_connection_error_with_reason_handler(
base::Bind(ClientLayerTreeFrameSink::OnMojoConnectionError));
compositor_frame_sink_ptr_ = compositor_frame_sink_associated_.get();
}
client_binding_.Bind(std::move(pipes_.client_request));
if (synthetic_begin_frame_source_) {
client->SetBeginFrameSource(synthetic_begin_frame_source_.get());
} else {
begin_frame_source_ = base::MakeUnique<ExternalBeginFrameSource>(this);
begin_frame_source_->OnSetBeginFrameSourcePaused(begin_frames_paused_);
client->SetBeginFrameSource(begin_frame_source_.get());
}
return true;
}
void ClientLayerTreeFrameSink::DetachFromClient() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
client_->SetBeginFrameSource(nullptr);
begin_frame_source_.reset();
synthetic_begin_frame_source_.reset();
client_binding_.Close();
compositor_frame_sink_.reset();
compositor_frame_sink_associated_.reset();
compositor_frame_sink_ptr_ = nullptr;
cc::LayerTreeFrameSink::DetachFromClient();
}
void ClientLayerTreeFrameSink::SetLocalSurfaceId(
const LocalSurfaceId& local_surface_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(local_surface_id.is_valid());
DCHECK(enable_surface_synchronization_);
local_surface_id_ = local_surface_id;
}
void ClientLayerTreeFrameSink::SubmitCompositorFrame(CompositorFrame frame) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(compositor_frame_sink_ptr_);
DCHECK(frame.metadata.begin_frame_ack.has_damage);
DCHECK_LE(BeginFrameArgs::kStartingFrameNumber,
frame.metadata.begin_frame_ack.sequence_number);
if (!enable_surface_synchronization_) {
local_surface_id_ =
local_surface_id_provider_->GetLocalSurfaceIdForFrame(frame);
}
TRACE_EVENT_FLOW_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"),
"SubmitCompositorFrame",
local_surface_id_.local_id());
bool tracing_enabled;
TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("cc.debug.ipc"),
&tracing_enabled);
mojom::HitTestRegionListPtr hit_test_region_list;
if (hit_test_data_provider_)
hit_test_region_list = hit_test_data_provider_->GetHitTestData();
compositor_frame_sink_ptr_->SubmitCompositorFrame(
local_surface_id_, std::move(frame), std::move(hit_test_region_list),
tracing_enabled ? base::TimeTicks::Now().since_origin().InMicroseconds()
: 0);
}
void ClientLayerTreeFrameSink::DidNotProduceFrame(const BeginFrameAck& ack) {
DCHECK(compositor_frame_sink_ptr_);
DCHECK(!ack.has_damage);
DCHECK_LE(BeginFrameArgs::kStartingFrameNumber, ack.sequence_number);
compositor_frame_sink_ptr_->DidNotProduceFrame(ack);
}
void ClientLayerTreeFrameSink::DidReceiveCompositorFrameAck(
const std::vector<ReturnedResource>& resources) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
client_->ReclaimResources(resources);
client_->DidReceiveCompositorFrameAck();
}
void ClientLayerTreeFrameSink::DidPresentCompositorFrame(
uint32_t presentation_token,
base::TimeTicks time,
base::TimeDelta refresh,
uint32_t flags) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
client_->DidPresentCompositorFrame(presentation_token, time, refresh, flags);
}
void ClientLayerTreeFrameSink::DidDiscardCompositorFrame(
uint32_t presentation_token) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
client_->DidDiscardCompositorFrame(presentation_token);
}
void ClientLayerTreeFrameSink::OnBeginFrame(const BeginFrameArgs& args) {
if (!needs_begin_frames_) {
// We had a race with SetNeedsBeginFrame(false) and still need to let the
// sink know that we didn't use this BeginFrame.
DidNotProduceFrame(
BeginFrameAck(args.source_id, args.sequence_number, false));
}
if (begin_frame_source_)
begin_frame_source_->OnBeginFrame(args);
}
void ClientLayerTreeFrameSink::OnBeginFramePausedChanged(bool paused) {
begin_frames_paused_ = paused;
if (begin_frame_source_)
begin_frame_source_->OnSetBeginFrameSourcePaused(paused);
}
void ClientLayerTreeFrameSink::ReclaimResources(
const std::vector<ReturnedResource>& resources) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
client_->ReclaimResources(resources);
}
void ClientLayerTreeFrameSink::OnNeedsBeginFrames(bool needs_begin_frames) {
DCHECK(compositor_frame_sink_ptr_);
needs_begin_frames_ = needs_begin_frames;
compositor_frame_sink_ptr_->SetNeedsBeginFrame(needs_begin_frames);
}
// static
void ClientLayerTreeFrameSink::OnMojoConnectionError(
uint32_t custom_reason,
const std::string& description) {
if (custom_reason)
DLOG(FATAL) << description;
}
} // namespace viz