blob: 748f9cb7966a6c23cadeb0dd01088f6b527242eb [file] [log] [blame]
// Copyright 2014 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 "ui/compositor/test/direct_layer_tree_frame_sink.h"
#include <memory>
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/trees/layer_tree_frame_sink_client.h"
#include "components/viz/common/hit_test/hit_test_region_list.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/display/display.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface.h"
namespace ui {
DirectLayerTreeFrameSink::DirectLayerTreeFrameSink(
const viz::FrameSinkId& frame_sink_id,
viz::FrameSinkManagerImpl* frame_sink_manager,
viz::Display* display,
scoped_refptr<viz::ContextProvider> context_provider,
scoped_refptr<viz::RasterContextProvider> worker_context_provider,
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
: LayerTreeFrameSink(std::move(context_provider),
std::move(worker_context_provider),
std::move(compositor_task_runner),
gpu_memory_buffer_manager),
frame_sink_id_(frame_sink_id),
frame_sink_manager_(frame_sink_manager),
display_(display) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
DirectLayerTreeFrameSink::~DirectLayerTreeFrameSink() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
bool DirectLayerTreeFrameSink::BindToClient(
cc::LayerTreeFrameSinkClient* client) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!cc::LayerTreeFrameSink::BindToClient(client))
return false;
support_ = std::make_unique<viz::CompositorFrameSinkSupport>(
this, frame_sink_manager_, frame_sink_id_, /*is_root=*/true);
begin_frame_source_ = std::make_unique<viz::ExternalBeginFrameSource>(this);
client_->SetBeginFrameSource(begin_frame_source_.get());
// Avoid initializing GL context here, as this should be sharing the
// Display's context.
display_->Initialize(this, frame_sink_manager_->surface_manager());
support_->SetUpHitTest(display_);
return true;
}
void DirectLayerTreeFrameSink::DetachFromClient() {
client_->SetBeginFrameSource(nullptr);
begin_frame_source_.reset();
// Unregister the SurfaceFactoryClient here instead of the dtor so that only
// one client is alive for this namespace at any given time.
support_.reset();
cc::LayerTreeFrameSink::DetachFromClient();
}
void DirectLayerTreeFrameSink::SubmitCompositorFrame(
viz::CompositorFrame frame,
bool hit_test_data_changed,
bool show_hit_test_borders) {
DCHECK(frame.metadata.begin_frame_ack.has_damage);
DCHECK(frame.metadata.begin_frame_ack.frame_id.IsSequenceValid());
if (frame.size_in_pixels() != last_swap_frame_size_ ||
frame.device_scale_factor() != device_scale_factor_ ||
!parent_local_surface_id_allocator_.HasValidLocalSurfaceId()) {
parent_local_surface_id_allocator_.GenerateId();
last_swap_frame_size_ = frame.size_in_pixels();
device_scale_factor_ = frame.device_scale_factor();
display_->SetLocalSurfaceId(
parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
device_scale_factor_);
}
base::Optional<viz::HitTestRegionList> hit_test_region_list =
client_->BuildHitTestData();
if (!hit_test_region_list) {
last_hit_test_data_ = viz::HitTestRegionList();
} else if (!hit_test_data_changed) {
// Do not send duplicate hit-test data.
if (viz::HitTestRegionList::IsEqual(*hit_test_region_list,
last_hit_test_data_)) {
DCHECK(!viz::HitTestRegionList::IsEqual(*hit_test_region_list,
viz::HitTestRegionList()));
hit_test_region_list = base::nullopt;
} else {
last_hit_test_data_ = *hit_test_region_list;
}
} else {
last_hit_test_data_ = *hit_test_region_list;
}
support_->SubmitCompositorFrame(
parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
std::move(frame), std::move(hit_test_region_list));
}
void DirectLayerTreeFrameSink::DidNotProduceFrame(
const viz::BeginFrameAck& ack) {
DCHECK(!ack.has_damage);
DCHECK(ack.frame_id.IsSequenceValid());
support_->DidNotProduceFrame(ack);
}
void DirectLayerTreeFrameSink::DidAllocateSharedBitmap(
base::ReadOnlySharedMemoryRegion region,
const viz::SharedBitmapId& id) {
bool ok = support_->DidAllocateSharedBitmap(std::move(region), id);
DCHECK(ok);
}
void DirectLayerTreeFrameSink::DidDeleteSharedBitmap(
const viz::SharedBitmapId& id) {
support_->DidDeleteSharedBitmap(id);
}
void DirectLayerTreeFrameSink::DisplayOutputSurfaceLost() {
is_lost_ = true;
client_->DidLoseLayerTreeFrameSink();
}
void DirectLayerTreeFrameSink::DisplayWillDrawAndSwap(
bool will_draw_and_swap,
viz::AggregatedRenderPassList* render_passes) {
if (support_->GetHitTestAggregator()) {
support_->GetHitTestAggregator()->Aggregate(display_->CurrentSurfaceId(),
render_passes);
}
}
base::TimeDelta
DirectLayerTreeFrameSink::GetPreferredFrameIntervalForFrameSinkId(
const viz::FrameSinkId& id,
viz::mojom::CompositorFrameSinkType* type) {
return frame_sink_manager_->GetPreferredFrameIntervalForFrameSinkId(id, type);
}
void DirectLayerTreeFrameSink::DidReceiveCompositorFrameAck(
const std::vector<viz::ReturnedResource>& resources) {
// Submitting a CompositorFrame can synchronously draw and dispatch a frame
// ack. PostTask to ensure the client is notified on a new stack frame.
compositor_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&DirectLayerTreeFrameSink::DidReceiveCompositorFrameAckInternal,
weak_factory_.GetWeakPtr(), resources));
}
void DirectLayerTreeFrameSink::DidReceiveCompositorFrameAckInternal(
const std::vector<viz::ReturnedResource>& resources) {
client_->ReclaimResources(resources);
client_->DidReceiveCompositorFrameAck();
}
void DirectLayerTreeFrameSink::OnBeginFrame(
const viz::BeginFrameArgs& args,
const viz::FrameTimingDetailsMap& timing_details) {
for (const auto& pair : timing_details)
client_->DidPresentCompositorFrame(pair.first, pair.second);
if (!needs_begin_frames_) {
// OnBeginFrame() can be called just to deliver presentation feedback, so
// report that we didn't use this BeginFrame.
DidNotProduceFrame(viz::BeginFrameAck(args, false));
return;
}
begin_frame_source_->OnBeginFrame(args);
}
void DirectLayerTreeFrameSink::ReclaimResources(
const std::vector<viz::ReturnedResource>& resources) {
client_->ReclaimResources(resources);
}
void DirectLayerTreeFrameSink::OnBeginFramePausedChanged(bool paused) {
begin_frame_source_->OnSetBeginFrameSourcePaused(paused);
}
void DirectLayerTreeFrameSink::OnNeedsBeginFrames(bool needs_begin_frames) {
needs_begin_frames_ = needs_begin_frames;
support_->SetNeedsBeginFrame(needs_begin_frames);
}
} // namespace ui