Commit 9dc83102 authored by Gary Klassen's avatar Gary Klassen Committed by Commit Bot

Route HitTestRegionList through FrameSinkManager

This change routes HitTestRegionList objects received by
CompositorFrameSinkSupport to the HitTestManager.

The HitTestAggregator will query the HitTestManager for the
active HitTestRegionLists when aggregating the data.

HitTestManager also manages the lifetime of HitTestRegionList
objects by deleting old objects when surfaces are discarded
and deleting objects that correspond to older frames when
a new surface is activated.

This change also modifies HitTestAggregator memory management
so that new memory is allocated as needed while aggregating
HitTestRegionList data.

Bug: 732399
Change-Id: Iaedec31a34f04446a539acd10d77c6fe18034d44
Reviewed-on: https://chromium-review.googlesource.com/650220
Commit-Queue: Gary Klassen <gklassen@chromium.org>
Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Reviewed-by: default avatarRia Jiang <riajiang@chromium.org>
Reviewed-by: default avatarFady Samuel <fsamuel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#506780}
parent 30f568cb
......@@ -110,6 +110,8 @@ viz_component("service") {
"hit_test/hit_test_aggregator.cc",
"hit_test/hit_test_aggregator.h",
"hit_test/hit_test_aggregator_delegate.h",
"hit_test/hit_test_manager.cc",
"hit_test/hit_test_manager.h",
"surfaces/direct_surface_reference_factory.cc",
"surfaces/direct_surface_reference_factory.h",
"surfaces/surface.cc",
......
......@@ -172,9 +172,6 @@ bool CompositorFrameSinkSupport::SubmitCompositorFrame(
}
}
frame_sink_manager()->SubmitHitTestRegionList(
current_surface_id_, frame_index, std::move(hit_test_region_list));
Surface* prev_surface =
surface_manager_->GetSurfaceForId(current_surface_id_);
Surface* current_surface = nullptr;
......@@ -219,6 +216,9 @@ bool CompositorFrameSinkSupport::SubmitCompositorFrame(
surface_manager_->DestroySurface(prev_surface->surface_id());
}
frame_sink_manager()->SubmitHitTestRegionList(
current_surface_id_, frame_index, std::move(hit_test_region_list));
if (begin_frame_source_)
begin_frame_source_->DidFinishFrame(this);
......
......@@ -35,7 +35,9 @@ FrameSinkManagerImpl::FrameSinkManagerImpl(
DisplayProvider* display_provider)
: display_provider_(display_provider),
surface_manager_(lifetime_type),
hit_test_manager_(this),
binding_(this) {
surface_manager_.AddObserver(&hit_test_manager_);
surface_manager_.AddObserver(this);
}
......@@ -47,6 +49,7 @@ FrameSinkManagerImpl::~FrameSinkManagerImpl() {
DCHECK_EQ(clients_.size(), 0u);
DCHECK_EQ(registered_sources_.size(), 0u);
surface_manager_.RemoveObserver(this);
surface_manager_.RemoveObserver(&hit_test_manager_);
}
void FrameSinkManagerImpl::BindAndSetClient(
......@@ -368,8 +371,13 @@ void FrameSinkManagerImpl::SubmitHitTestRegionList(
const SurfaceId& surface_id,
uint64_t frame_index,
mojom::HitTestRegionListPtr hit_test_region_list) {
// TODO(gklassen): Route hit_test_region_list to appropriate
// matching RootCompositorFrameSink
hit_test_manager_.SubmitHitTestRegionList(surface_id, frame_index,
std::move(hit_test_region_list));
}
uint64_t FrameSinkManagerImpl::GetActiveFrameIndex(
const SurfaceId& surface_id) {
return surface_manager_.GetSurfaceForId(surface_id)->GetActiveFrameIndex();
}
void FrameSinkManagerImpl::OnAggregatedHitTestRegionListUpdated(
......
......@@ -16,6 +16,7 @@
#include "base/threading/thread_checker.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/service/frame_sinks/primary_begin_frame_source.h"
#include "components/viz/service/hit_test/hit_test_manager.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "components/viz/service/surfaces/surface_observer.h"
#include "components/viz/service/viz_service_export.h"
......@@ -112,6 +113,8 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl : public SurfaceObserver,
SurfaceManager* surface_manager() { return &surface_manager_; }
const HitTestManager* hit_test_manager() { return &hit_test_manager_; }
// SurfaceObserver implementation.
void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override;
void OnSurfaceActivated(const SurfaceId& surface_id) override;
......@@ -146,6 +149,9 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl : public SurfaceObserver,
uint64_t frame_index,
mojom::HitTestRegionListPtr hit_test_region_list);
// This method is virtual so the implementation can be modified in unit tests.
virtual uint64_t GetActiveFrameIndex(const SurfaceId& surface_id);
private:
friend class cc::test::SurfaceSynchronizationTest;
......@@ -191,6 +197,8 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl : public SurfaceObserver,
// surfaces are destroyed before |primary_source_|.
SurfaceManager surface_manager_;
HitTestManager hit_test_manager_;
std::unordered_map<FrameSinkId,
std::unique_ptr<mojom::CompositorFrameSink>,
FrameSinkIdHash>
......
......@@ -31,7 +31,7 @@ RootCompositorFrameSinkImpl::RootCompositorFrameSinkImpl(
true /* needs_sync_points */)),
display_begin_frame_source_(std::move(begin_frame_source)),
display_(std::move(display)),
hit_test_aggregator_(this) {
hit_test_aggregator_(frame_sink_manager->hit_test_manager(), this) {
DCHECK(display_begin_frame_source_);
DCHECK(display_);
......
......@@ -15,30 +15,8 @@ namespace {
// telemetry / UMA.
constexpr uint32_t kInitialSize = 1024;
constexpr uint32_t kIncrementalSize = 1024;
constexpr uint32_t kMaxRegionsPerSurface = 1024;
constexpr uint32_t kMaxSize = 100 * 1024;
bool ValidateHitTestRegion(const mojom::HitTestRegionPtr& hit_test_region) {
if (hit_test_region->flags & mojom::kHitTestChildSurface) {
if (!hit_test_region->local_surface_id.has_value() ||
!hit_test_region->local_surface_id->is_valid())
return false;
}
return true;
}
bool ValidateHitTestRegionList(
const mojom::HitTestRegionListPtr& hit_test_region_list) {
if (hit_test_region_list->regions.size() > kMaxRegionsPerSurface)
return false;
for (auto& region : hit_test_region_list->regions) {
if (!ValidateHitTestRegion(region))
return false;
}
return true;
}
void PrepareTransformForReadOnlySharedMemory(gfx::Transform* transform) {
// |transform| is going to be shared in read-only memory to HitTestQuery.
// However, if HitTestQuery tries to operate on it, then it is possible that
......@@ -52,23 +30,16 @@ void PrepareTransformForReadOnlySharedMemory(gfx::Transform* transform) {
} // namespace
HitTestAggregator::HitTestAggregator(HitTestAggregatorDelegate* delegate)
: delegate_(delegate), weak_ptr_factory_(this) {
HitTestAggregator::HitTestAggregator(const HitTestManager* hit_test_manager,
HitTestAggregatorDelegate* delegate)
: hit_test_manager_(hit_test_manager),
delegate_(delegate),
weak_ptr_factory_(this) {
AllocateHitTestRegionArray();
}
HitTestAggregator::~HitTestAggregator() = default;
void HitTestAggregator::SubmitHitTestRegionList(
const SurfaceId& frame_sink_id,
mojom::HitTestRegionListPtr hit_test_region_list) {
DCHECK(ValidateHitTestRegionList(hit_test_region_list));
// TODO(gklassen): Runtime validation that hit_test_region_list is valid.
// TODO(gklassen): Inform FrameSink that the hit_test_region_list is invalid.
// TODO(gklassen): FrameSink needs to inform the host of a difficult renderer.
pending_[frame_sink_id] = std::move(hit_test_region_list);
}
void HitTestAggregator::PostTaskAggregate(const SurfaceId& display_surface_id) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
......@@ -77,18 +48,12 @@ void HitTestAggregator::PostTaskAggregate(const SurfaceId& display_surface_id) {
}
void HitTestAggregator::Aggregate(const SurfaceId& display_surface_id) {
// Check to ensure that enough memory has been allocated.
uint32_t size = write_size_;
uint32_t max_size = active_region_count_ + active_.size() + 1;
if (max_size > kMaxSize)
max_size = kMaxSize;
if (max_size > size) {
size = (1 + max_size / kIncrementalSize) * kIncrementalSize;
AllocateHitTestRegionArray(size);
}
AppendRoot(display_surface_id);
Swap();
}
void HitTestAggregator::GrowRegionList() {
ResizeHitTestRegionArray(write_size_ + kIncrementalSize);
}
void HitTestAggregator::Swap() {
......@@ -107,62 +72,26 @@ void HitTestAggregator::Swap() {
handle_replaced_ = false;
}
bool HitTestAggregator::OnSurfaceDamaged(const SurfaceId& surface_id,
const BeginFrameAck& ack) {
return false;
}
void HitTestAggregator::OnSurfaceDiscarded(const SurfaceId& surface_id) {
// Update the region count.
auto active_search = active_.find(surface_id);
if (active_search != active_.end()) {
mojom::HitTestRegionList* old_hit_test_data = active_search->second.get();
active_region_count_ -= old_hit_test_data->regions.size();
}
DCHECK_GE(active_region_count_, 0u);
pending_.erase(surface_id);
active_.erase(surface_id);
}
void HitTestAggregator::OnSurfaceWillDraw(const SurfaceId& surface_id) {
auto pending_search = pending_.find(surface_id);
if (pending_search == pending_.end()) {
// Have already activated pending hit_test_region_list objects for this
// surface.
return;
}
mojom::HitTestRegionList* hit_test_region_list = pending_search->second.get();
// Update the region count.
auto active_search = active_.find(surface_id);
if (active_search != active_.end()) {
mojom::HitTestRegionList* old_hit_test_data = active_search->second.get();
active_region_count_ -= old_hit_test_data->regions.size();
}
active_region_count_ += hit_test_region_list->regions.size();
DCHECK_GE(active_region_count_, 0u);
active_[surface_id] = std::move(pending_[surface_id]);
pending_.erase(surface_id);
}
void HitTestAggregator::AllocateHitTestRegionArray() {
AllocateHitTestRegionArray(kInitialSize);
ResizeHitTestRegionArray(kInitialSize);
SwapHandles();
AllocateHitTestRegionArray(kInitialSize);
ResizeHitTestRegionArray(kInitialSize);
}
void HitTestAggregator::AllocateHitTestRegionArray(uint32_t size) {
void HitTestAggregator::ResizeHitTestRegionArray(uint32_t size) {
size_t num_bytes = size * sizeof(AggregatedHitTestRegion);
write_handle_ = mojo::SharedBufferHandle::Create(num_bytes);
write_size_ = size;
write_buffer_ = write_handle_->Map(num_bytes);
auto new_buffer_ = write_handle_->Map(num_bytes);
handle_replaced_ = true;
AggregatedHitTestRegion* region =
(AggregatedHitTestRegion*)write_buffer_.get();
region[0].child_count = kEndOfList;
AggregatedHitTestRegion* region = (AggregatedHitTestRegion*)new_buffer_.get();
if (write_size_)
memcpy(region, write_buffer_.get(), write_size_);
else
region[0].child_count = kEndOfList;
write_size_ = size;
write_buffer_ = std::move(new_buffer_);
}
void HitTestAggregator::SwapHandles() {
......@@ -175,54 +104,47 @@ void HitTestAggregator::SwapHandles() {
}
void HitTestAggregator::AppendRoot(const SurfaceId& surface_id) {
auto search = active_.find(surface_id);
if (search == active_.end())
const mojom::HitTestRegionList* hit_test_region_list =
hit_test_manager_->GetActiveHitTestRegionList(surface_id);
if (!hit_test_region_list)
return;
mojom::HitTestRegionList* hit_test_region_list = search->second.get();
AggregatedHitTestRegion* regions =
static_cast<AggregatedHitTestRegion*>(write_buffer_.get());
regions[0].frame_sink_id = surface_id.frame_sink_id();
regions[0].flags = hit_test_region_list->flags;
regions[0].rect = hit_test_region_list->bounds;
regions[0].transform = hit_test_region_list->transform;
PrepareTransformForReadOnlySharedMemory(&regions[0].transform);
size_t region_index = 1;
for (const auto& region : hit_test_region_list->regions) {
if (region_index >= write_size_ - 1)
break;
region_index = AppendRegion(regions, region_index, region);
region_index = AppendRegion(region_index, region);
}
DCHECK_GE(region_index, 1u);
regions[0].child_count = region_index - 1;
regions[region_index].child_count = kEndOfList;
int32_t child_count = region_index - 1;
SetRegionAt(0, surface_id.frame_sink_id(), hit_test_region_list->flags,
hit_test_region_list->bounds, hit_test_region_list->transform,
child_count);
MarkEndAt(region_index);
}
size_t HitTestAggregator::AppendRegion(AggregatedHitTestRegion* regions,
size_t region_index,
size_t HitTestAggregator::AppendRegion(size_t region_index,
const mojom::HitTestRegionPtr& region) {
AggregatedHitTestRegion* element = &regions[region_index];
element->frame_sink_id = region->frame_sink_id;
element->flags = region->flags;
element->rect = region->rect;
element->transform = region->transform;
size_t parent_index = region_index++;
if (region_index >= write_size_ - 1) {
element->child_count = 0;
return region_index;
if (write_size_ > kMaxSize) {
MarkEndAt(parent_index);
return region_index;
} else {
GrowRegionList();
}
}
uint32_t flags = region->flags;
gfx::Transform transform = region->transform;
if (region->flags & mojom::kHitTestChildSurface) {
auto surface_id =
SurfaceId(region->frame_sink_id, region->local_surface_id.value());
auto search = active_.find(surface_id);
if (search == active_.end()) {
const mojom::HitTestRegionList* hit_test_region_list =
hit_test_manager_->GetActiveHitTestRegionList(surface_id);
if (!hit_test_region_list) {
// Surface HitTestRegionList not found - it may be late.
// Don't include this region so that it doesn't receive events.
return parent_index;
......@@ -231,22 +153,47 @@ size_t HitTestAggregator::AppendRegion(AggregatedHitTestRegion* regions,
// Rather than add a node in the tree for this hit_test_region_list element
// we can simplify the tree by merging the flags and transform into
// the kHitTestChildSurface element.
mojom::HitTestRegionList* hit_test_region_list = search->second.get();
if (!hit_test_region_list->transform.IsIdentity())
element->transform.PreconcatTransform(hit_test_region_list->transform);
transform.PreconcatTransform(hit_test_region_list->transform);
element->flags |= hit_test_region_list->flags;
flags |= hit_test_region_list->flags;
for (const auto& child_region : hit_test_region_list->regions) {
region_index = AppendRegion(regions, region_index, child_region);
region_index = AppendRegion(region_index, child_region);
if (region_index >= write_size_ - 1)
break;
}
}
PrepareTransformForReadOnlySharedMemory(&element->transform);
DCHECK_GE(region_index - parent_index - 1, 0u);
element->child_count = region_index - parent_index - 1;
int32_t child_count = region_index - parent_index - 1;
SetRegionAt(parent_index, region->frame_sink_id, flags, region->rect,
transform, child_count);
return region_index;
}
void HitTestAggregator::SetRegionAt(size_t index,
const FrameSinkId& frame_sink_id,
uint32_t flags,
const gfx::Rect& rect,
const gfx::Transform& transform,
int32_t child_count) {
AggregatedHitTestRegion* regions =
static_cast<AggregatedHitTestRegion*>(write_buffer_.get());
AggregatedHitTestRegion* element = &regions[index];
element->frame_sink_id = frame_sink_id;
element->flags = flags;
element->rect = rect;
element->transform = transform;
element->child_count = child_count;
PrepareTransformForReadOnlySharedMemory(&element->transform);
}
void HitTestAggregator::MarkEndAt(size_t index) {
AggregatedHitTestRegion* regions =
static_cast<AggregatedHitTestRegion*>(write_buffer_.get());
regions[index].child_count = kEndOfList;
}
} // namespace viz
......@@ -7,6 +7,7 @@
#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/service/hit_test/hit_test_manager.h"
#include "components/viz/service/surfaces/surface_observer.h"
#include "components/viz/service/viz_service_export.h"
#include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
......@@ -14,25 +15,21 @@
namespace viz {
class HitTestAggregatorDelegate;
// HitTestAggregator collects HitTestRegionList objects from surfaces and
// aggregates them into a DisplayHitTesData structue made available in
// shared memory to enable efficient hit testing across processes.
// HitTestAggregator assembles the list of HitTestRegion objects that define the
// hit test information required for one display. Active HitTestRegionList
// information is obtained from the HitTestManager. The resulting list is made
// available in shared memory and used by HitTestQuery to enable efficient hit
// testing across processes.
//
// This is intended to be created in the viz or GPU process. For mus+ash this
// will be true after the mus process split.
class VIZ_SERVICE_EXPORT HitTestAggregator : public SurfaceObserver {
class VIZ_SERVICE_EXPORT HitTestAggregator {
public:
// |delegate| owns and outlives HitTestAggregator.
explicit HitTestAggregator(HitTestAggregatorDelegate* delegate);
HitTestAggregator(const HitTestManager* hit_test_manager,
HitTestAggregatorDelegate* delegate);
~HitTestAggregator();
// Called when HitTestRegionList is submitted along with every call
// to SubmitCompositorFrame. This is collected in pending_ until
// surfaces are aggregated and put on the display.
void SubmitHitTestRegionList(
const SurfaceId& surface_id,
mojom::HitTestRegionListPtr hit_test_region_list);
// Performs the work of Aggregate by creating a PostTask so that
// the work is not directly on the call.
void PostTaskAggregate(const SurfaceId& display_surface_id);
......@@ -47,34 +44,10 @@ class VIZ_SERVICE_EXPORT HitTestAggregator : public SurfaceObserver {
// delegate.
void Swap();
protected:
// SurfaceObserver:
void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override {}
void OnSurfaceActivated(const SurfaceId& surface_id) override {}
void OnSurfaceDestroyed(const SurfaceId& surface_id) override {}
bool OnSurfaceDamaged(const SurfaceId& surface_id,
const BeginFrameAck& ack) override;
void OnSurfaceDiscarded(const SurfaceId& surface_id) override;
void OnSurfaceDamageExpected(const SurfaceId& surface_id,
const BeginFrameArgs& args) override {}
// Called when a surface has been aggregated and added to the
// display frame. HitTestRegionList objects are held but ignored until
// this happens. HitTestRegionList for the surface is copied from |pending_|
// to |active_| in this method.
void OnSurfaceWillDraw(const SurfaceId& surface_id) override;
// The collection of received HitTestRegionList objects that have not yet
// been added to the DisplayFrame (OnSurfaceWillDraw has not been called).
std::map<SurfaceId, mojom::HitTestRegionListPtr> pending_;
// The collection of HitTestRegionList objects that have been added to the
// DisplayFrame (OnSurfaceWillDraw has been called).
std::map<SurfaceId, mojom::HitTestRegionListPtr> active_;
// Keeps track of the number of regions in the active list
// so that we know when we exceed the available length.
uint32_t active_region_count_ = 0;
private:
friend class TestHitTestAggregator;
const HitTestManager* const hit_test_manager_;
mojo::ScopedSharedBufferHandle read_handle_;
mojo::ScopedSharedBufferHandle write_handle_;
......@@ -93,22 +66,37 @@ class VIZ_SERVICE_EXPORT HitTestAggregator : public SurfaceObserver {
HitTestAggregatorDelegate* const delegate_;
private:
// Allocates memory for the AggregatedHitTestRegion array.
void AllocateHitTestRegionArray();
void AllocateHitTestRegionArray(uint32_t length);
// Resizes memory for the AggregatedHitTestRegion array. |size| indicates the
// number of elements.
void ResizeHitTestRegionArray(uint32_t size);
void GrowRegionList();
void SwapHandles();
// Appends the root element to the AggregatedHitTestRegion array.
void AppendRoot(const SurfaceId& surface_id);
// Appends a region to the HitTestRegionList structure to recursively
// build the tree.
size_t AppendRegion(AggregatedHitTestRegion* regions,
size_t region_index,
// Appends a |region| to the HitTestRegionList structure to recursively
// build the tree. |region_index| indicates the current index of the end of
// the list.
size_t AppendRegion(size_t region_index,
const mojom::HitTestRegionPtr& region);
// Populates the HitTestRegion element at the given element |index|.
// Access to the HitTestRegion list is localized to this call
// in order to prevent errors if the array is resized during aggregation.
void SetRegionAt(size_t index,
const FrameSinkId& frame_sink_id,
uint32_t flags,
const gfx::Rect& rect,
const gfx::Transform& transform,
int32_t child_count);
// Marks the element at the given index as the end of list.
void MarkEndAt(size_t index);
// Handles the case when this object is deleted after
// the PostTaskAggregation call is scheduled but before invocation.
base::WeakPtrFactory<HitTestAggregator> weak_ptr_factory_;
......
......@@ -26,32 +26,23 @@ SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t local_id) {
LocalSurfaceId(local_id, base::UnguessableToken::Deserialize(0, 1u)));
}
} // namespace
class TestHitTestAggregator final : public HitTestAggregator {
public:
explicit TestHitTestAggregator(HitTestAggregatorDelegate* delegate)
: HitTestAggregator(delegate) {}
TestHitTestAggregator(HitTestManager* manager,
HitTestAggregatorDelegate* delegate)
: HitTestAggregator(manager, delegate) {}
~TestHitTestAggregator() = default;
void CallOnSurfaceWillDraw(SurfaceId surface_id) {
OnSurfaceWillDraw(surface_id);
}
void CallOnSurfaceDiscarded(SurfaceId surface_id) {
OnSurfaceDiscarded(surface_id);
}
int Count() {
int GetRegionCount() const {
AggregatedHitTestRegion* start =
static_cast<AggregatedHitTestRegion*>(read_buffer_.get());
AggregatedHitTestRegion* end = start;
while (end->child_count != kEndOfList)
end++;
int count = end - start;
return count;
return end - start;
}
int GetPendingCount() { return pending_.size(); }
int GetActiveCount() { return active_.size(); }
int GetActiveRegionCount() { return active_region_count_; }
int GetHitTestRegionListSize() { return read_size_; }
void SwapHandles() {
delegate_->SwitchActiveAggregatedHitTestRegionList(active_handle_index_);
......@@ -64,21 +55,48 @@ class TestHitTestAggregator final : public HitTestAggregator {
regions = static_cast<AggregatedHitTestRegion*>(read_buffer_.get());
regions[0].child_count = kEndOfList;
pending_.clear();
active_.clear();
}
};
namespace {
class TestFrameSinkManagerImpl;
} // namespace
class TestHitTestManager : public HitTestManager {
public:
explicit TestHitTestManager(TestFrameSinkManagerImpl* frame_sink_manager);
~TestHitTestManager() override = default;
void CallOnSurfaceActivated(const SurfaceId surface_id) {
OnSurfaceActivated(surface_id);
}
void CallOnSurfaceDiscarded(const SurfaceId surface_id) {
OnSurfaceDiscarded(surface_id);
}
void Reset() { hit_test_region_lists_.clear(); }
int GetRegionCount() {
int count = 0;
for (auto& i : hit_test_region_lists_) {
count += i.second.size();
}
return count;
}
};
namespace {
class TestGpuRootCompositorFrameSink : public HitTestAggregatorDelegate {
public:
TestGpuRootCompositorFrameSink(TestFrameSinkManagerImpl* frame_sink_manager,
TestGpuRootCompositorFrameSink(TestHitTestManager* hit_test_manager,
TestFrameSinkManagerImpl* frame_sink_manager,
const FrameSinkId& frame_sink_id)
: frame_sink_manager_(frame_sink_manager),
frame_sink_id_(frame_sink_id),
aggregator_(base::MakeUnique<TestHitTestAggregator>(this)) {}
aggregator_(
base::MakeUnique<TestHitTestAggregator>(hit_test_manager, this)) {}
~TestGpuRootCompositorFrameSink() override = default;
// HitTestAggregatorDelegate:
......@@ -171,9 +189,11 @@ class TestFrameSinkManagerImpl : public FrameSinkManagerImpl {
}
}
void CreateRootCompositorFrameSinkLocal(const FrameSinkId& frame_sink_id) {
void CreateRootCompositorFrameSinkLocal(TestHitTestManager* hit_test_manager,
const FrameSinkId& frame_sink_id) {
compositor_frame_sinks_[frame_sink_id] =
base::MakeUnique<TestGpuRootCompositorFrameSink>(this, frame_sink_id);
base::MakeUnique<TestGpuRootCompositorFrameSink>(hit_test_manager, this,
frame_sink_id);
}
const std::map<FrameSinkId, std::unique_ptr<TestGpuRootCompositorFrameSink>>&
......@@ -181,6 +201,10 @@ class TestFrameSinkManagerImpl : public FrameSinkManagerImpl {
return compositor_frame_sinks_;
}
uint64_t GetActiveFrameIndex(const SurfaceId& surface_id) override {
return 0;
}
private:
std::map<FrameSinkId, std::unique_ptr<TestGpuRootCompositorFrameSink>>
compositor_frame_sinks_;
......@@ -207,6 +231,10 @@ void TestGpuRootCompositorFrameSink::SwitchActiveAggregatedHitTestRegionList(
} // namespace
TestHitTestManager::TestHitTestManager(
TestFrameSinkManagerImpl* frame_sink_manager)
: HitTestManager(frame_sink_manager) {}
class HitTestAggregatorTest : public testing::Test {
public:
HitTestAggregatorTest() = default;
......@@ -216,12 +244,16 @@ class HitTestAggregatorTest : public testing::Test {
void SetUp() override {
frame_sink_manager_ = base::MakeUnique<TestFrameSinkManagerImpl>();
host_frame_sink_manager_ = base::MakeUnique<TestHostFrameSinkManager>();
hit_test_manager_ =
base::MakeUnique<TestHitTestManager>(frame_sink_manager_.get());
frame_sink_manager_->SetLocalClient(host_frame_sink_manager_.get());
frame_sink_manager_->CreateRootCompositorFrameSinkLocal(kDisplayFrameSink);
frame_sink_manager_->CreateRootCompositorFrameSinkLocal(
hit_test_manager_.get(), kDisplayFrameSink);
}
void TearDown() override {
frame_sink_manager_.reset();
host_frame_sink_manager_.reset();
hit_test_manager_.reset();
}
// Creates a hit test data element with 8 children recursively to
......@@ -251,8 +283,8 @@ class HitTestAggregatorTest : public testing::Test {
hit_test_region_list->regions.push_back(std::move(hit_test_region));
}
GetAggregator(kDisplayFrameSink)
->SubmitHitTestRegionList(surface_id, std::move(hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
surface_id, 0, std::move(hit_test_region_list));
return id;
}
......@@ -272,7 +304,10 @@ class HitTestAggregatorTest : public testing::Test {
return host_frame_sink_manager_->buffer_frame_sink_id();
}
TestHitTestManager* hit_test_manager() { return hit_test_manager_.get(); }
private:
std::unique_ptr<TestHitTestManager> hit_test_manager_;
std::unique_ptr<TestFrameSinkManagerImpl> frame_sink_manager_;
std::unique_ptr<TestHostFrameSinkManager> host_frame_sink_manager_;
......@@ -292,7 +327,7 @@ class HitTestAggregatorTest : public testing::Test {
//
TEST_F(HitTestAggregatorTest, OneSurface) {
TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetRegionCount(), 0);
SurfaceId display_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
......@@ -300,24 +335,13 @@ TEST_F(HitTestAggregatorTest, OneSurface) {
hit_test_region_list->flags = mojom::kHitTestMine;
hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
aggregator->SubmitHitTestRegionList(display_surface_id,
std::move(hit_test_region_list));
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetPendingCount(), 1);
EXPECT_EQ(aggregator->GetActiveCount(), 0);
aggregator->CallOnSurfaceWillDraw(display_surface_id);
EXPECT_EQ(aggregator->GetPendingCount(), 0);
EXPECT_EQ(aggregator->GetActiveCount(), 1);
hit_test_manager()->SubmitHitTestRegionList(display_surface_id, 0,
std::move(hit_test_region_list));
aggregator->Aggregate(display_surface_id);
aggregator->Swap();
aggregator->SwapHandles();
// Expect 1 entry routing all events to the one surface (display root).
EXPECT_EQ(aggregator->Count(), 1);
EXPECT_EQ(aggregator->GetRegionCount(), 1);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
AggregatedHitTestRegion* regions = host_regions();
......@@ -342,7 +366,7 @@ TEST_F(HitTestAggregatorTest, OneSurface) {
//
TEST_F(HitTestAggregatorTest, OneEmbedderTwoRegions) {
TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetRegionCount(), 0);
SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
......@@ -365,30 +389,15 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoRegions) {
e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_r1));
e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_r2));
// Submit mojom::HitTestRegionList.
EXPECT_EQ(aggregator->GetPendingCount(), 0);
aggregator->SubmitHitTestRegionList(e_surface_id,
std::move(e_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 1);
// Add Surfaces to DisplayFrame in unexpected order.
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetActiveCount(), 0);
aggregator->CallOnSurfaceWillDraw(e_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 1);
// Submit in unexpected order.
// Aggregate and swap.
hit_test_manager()->SubmitHitTestRegionList(
e_surface_id, 0, std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
EXPECT_EQ(aggregator->Count(), 0);
aggregator->Swap();
aggregator->SwapHandles();
EXPECT_EQ(aggregator->Count(), 3);
EXPECT_EQ(aggregator->GetRegionCount(), 3);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
AggregatedHitTestRegion* regions = host_regions();
......@@ -424,7 +433,7 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoRegions) {
TEST_F(HitTestAggregatorTest, OneEmbedderTwoChildren) {
TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetRegionCount(), 0);
SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
SurfaceId c1_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
......@@ -455,44 +464,17 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoChildren) {
// Submit in unexpected order.
EXPECT_EQ(aggregator->GetPendingCount(), 0);
aggregator->SubmitHitTestRegionList(c1_surface_id,
std::move(c1_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 1);
aggregator->SubmitHitTestRegionList(e_surface_id,
std::move(e_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 2);
aggregator->SubmitHitTestRegionList(c2_surface_id,
std::move(c2_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 3);
// Surfaces added to DisplayFrame in unexpected order.
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetActiveCount(), 0);
aggregator->CallOnSurfaceWillDraw(c2_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 1);
aggregator->CallOnSurfaceWillDraw(c1_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 2);
aggregator->CallOnSurfaceWillDraw(e_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 3);
// Aggregate and swap.
hit_test_manager()->SubmitHitTestRegionList(
c1_surface_id, 0, std::move(c1_hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
e_surface_id, 0, std::move(e_hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
c2_surface_id, 0, std::move(c2_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
EXPECT_EQ(aggregator->Count(), 0);
aggregator->Swap();
aggregator->SwapHandles();
EXPECT_EQ(aggregator->Count(), 3);
EXPECT_EQ(aggregator->GetRegionCount(), 3);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
AggregatedHitTestRegion* regions = host_regions();
......@@ -531,7 +513,7 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoChildren) {
TEST_F(HitTestAggregatorTest, OccludedChildFrame) {
TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetRegionCount(), 0);
SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
......@@ -561,37 +543,15 @@ TEST_F(HitTestAggregatorTest, OccludedChildFrame) {
// Submit in unexpected order.
EXPECT_EQ(aggregator->GetPendingCount(), 0);
aggregator->SubmitHitTestRegionList(c_surface_id,
std::move(c_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 1);
aggregator->SubmitHitTestRegionList(e_surface_id,
std::move(e_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 2);
// Surfaces added to DisplayFrame in unexpected order.
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetActiveCount(), 0);
aggregator->CallOnSurfaceWillDraw(e_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 1);
aggregator->CallOnSurfaceWillDraw(c_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 2);
// Aggregate and swap.
hit_test_manager()->SubmitHitTestRegionList(
c_surface_id, 0, std::move(c_hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
e_surface_id, 0, std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
EXPECT_EQ(aggregator->Count(), 0);
aggregator->Swap();
aggregator->SwapHandles();
EXPECT_EQ(aggregator->Count(), 3);
EXPECT_EQ(aggregator->GetRegionCount(), 3);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
AggregatedHitTestRegion* regions = host_regions();
......@@ -631,7 +591,7 @@ TEST_F(HitTestAggregatorTest, OccludedChildFrame) {
TEST_F(HitTestAggregatorTest, ForegroundChildFrame) {
TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetRegionCount(), 0);
SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
......@@ -661,37 +621,15 @@ TEST_F(HitTestAggregatorTest, ForegroundChildFrame) {
// Submit in unexpected order.
EXPECT_EQ(aggregator->GetPendingCount(), 0);
aggregator->SubmitHitTestRegionList(c_surface_id,
std::move(c_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 1);
aggregator->SubmitHitTestRegionList(e_surface_id,
std::move(e_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 2);
// Surfaces added to DisplayFrame in unexpected order.
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetActiveCount(), 0);
aggregator->CallOnSurfaceWillDraw(e_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 1);
aggregator->CallOnSurfaceWillDraw(c_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 2);
// Aggregate and swap.
hit_test_manager()->SubmitHitTestRegionList(
c_surface_id, 0, std::move(c_hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
e_surface_id, 0, std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
EXPECT_EQ(aggregator->Count(), 0);
aggregator->Swap();
aggregator->SwapHandles();
EXPECT_EQ(aggregator->Count(), 3);
EXPECT_EQ(aggregator->GetRegionCount(), 3);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
AggregatedHitTestRegion* regions = host_regions();
......@@ -731,7 +669,7 @@ TEST_F(HitTestAggregatorTest, ForegroundChildFrame) {
TEST_F(HitTestAggregatorTest, ClippedChildWithTabAndTransparentBackground) {
TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetRegionCount(), 0);
SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
......@@ -780,51 +718,19 @@ TEST_F(HitTestAggregatorTest, ClippedChildWithTabAndTransparentBackground) {
// Submit in unexpected order.
EXPECT_EQ(aggregator->GetPendingCount(), 0);
aggregator->SubmitHitTestRegionList(c_surface_id,
std::move(c_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 1);
aggregator->SubmitHitTestRegionList(a_surface_id,
std::move(a_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 2);
aggregator->SubmitHitTestRegionList(b_surface_id,
std::move(b_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 3);
aggregator->SubmitHitTestRegionList(e_surface_id,
std::move(e_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 4);
// Surfaces added to DisplayFrame in unexpected order.
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetActiveCount(), 0);
aggregator->CallOnSurfaceWillDraw(c_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 1);
aggregator->CallOnSurfaceWillDraw(e_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 2);
aggregator->CallOnSurfaceWillDraw(b_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 3);
aggregator->CallOnSurfaceWillDraw(a_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 4);
// Aggregate and swap.
hit_test_manager()->SubmitHitTestRegionList(
c_surface_id, 0, std::move(c_hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
a_surface_id, 0, std::move(a_hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
b_surface_id, 0, std::move(b_hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
e_surface_id, 0, std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
EXPECT_EQ(aggregator->Count(), 0);
aggregator->Swap();
aggregator->SwapHandles();
EXPECT_EQ(aggregator->Count(), 4);
EXPECT_EQ(aggregator->GetRegionCount(), 4);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
AggregatedHitTestRegion* regions = host_regions();
......@@ -876,7 +782,7 @@ TEST_F(HitTestAggregatorTest, ClippedChildWithTabAndTransparentBackground) {
TEST_F(HitTestAggregatorTest, ThreeChildrenDeep) {
TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetRegionCount(), 0);
SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
SurfaceId c1_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
......@@ -925,51 +831,19 @@ TEST_F(HitTestAggregatorTest, ThreeChildrenDeep) {
// Submit in unexpected order.
EXPECT_EQ(aggregator->GetPendingCount(), 0);
aggregator->SubmitHitTestRegionList(c1_surface_id,
std::move(c1_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 1);
aggregator->SubmitHitTestRegionList(c3_surface_id,
std::move(c3_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 2);
aggregator->SubmitHitTestRegionList(e_surface_id,
std::move(e_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 3);
aggregator->SubmitHitTestRegionList(c2_surface_id,
std::move(c2_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 4);
// Surfaces added to DisplayFrame in unexpected order.
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetActiveCount(), 0);
aggregator->CallOnSurfaceWillDraw(c2_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 1);
aggregator->CallOnSurfaceWillDraw(c1_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 2);
aggregator->CallOnSurfaceWillDraw(e_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 3);
aggregator->CallOnSurfaceWillDraw(c3_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 4);
// Aggregate and swap.
hit_test_manager()->SubmitHitTestRegionList(
c1_surface_id, 0, std::move(c1_hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
c3_surface_id, 0, std::move(c3_hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
e_surface_id, 0, std::move(e_hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
c2_surface_id, 0, std::move(c2_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
EXPECT_EQ(aggregator->Count(), 0);
aggregator->Swap();
aggregator->SwapHandles();
EXPECT_EQ(aggregator->Count(), 4);
EXPECT_EQ(aggregator->GetRegionCount(), 4);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
AggregatedHitTestRegion* regions = host_regions();
......@@ -1014,7 +888,7 @@ TEST_F(HitTestAggregatorTest, ThreeChildrenDeep) {
TEST_F(HitTestAggregatorTest, MissingChildFrame) {
TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetRegionCount(), 0);
SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
......@@ -1042,32 +916,15 @@ TEST_F(HitTestAggregatorTest, MissingChildFrame) {
c_hit_test_region_list->flags = mojom::kHitTestMine;
c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500);
// Submit in unexpected order, but not the child.
EXPECT_EQ(aggregator->GetPendingCount(), 0);
aggregator->SubmitHitTestRegionList(e_surface_id,
std::move(e_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 1);
// Surfaces added to DisplayFrame in unexpected order.
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetActiveCount(), 0);
aggregator->CallOnSurfaceWillDraw(e_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 1);
// Submit in unexpected order.
// Aggregate and swap.
hit_test_manager()->SubmitHitTestRegionList(
e_surface_id, 0, std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
EXPECT_EQ(aggregator->Count(), 0);
aggregator->Swap();
aggregator->SwapHandles();
EXPECT_EQ(aggregator->Count(), 2);
EXPECT_EQ(aggregator->GetRegionCount(), 2);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
AggregatedHitTestRegion* regions = host_regions();
......@@ -1112,34 +969,15 @@ TEST_F(HitTestAggregatorTest, MissingChildFrame) {
TEST_F(HitTestAggregatorTest, ExceedLimits) {
TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetRegionCount(), 0);
EXPECT_LT(aggregator->GetHitTestRegionListSize(), 4096);
SurfaceId display_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
int next_surface_id = CreateAndSubmitHitTestRegionListWith8Children(1, 3);
int surface_count = next_surface_id - 1;
EXPECT_EQ(aggregator->GetPendingCount(), surface_count);
CreateAndSubmitHitTestRegionListWith8Children(1, 3);
// Mark Surfaces as added to DisplayFrame in unexpected order.
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetActiveCount(), 0);
for (int i = 1; i <= surface_count; i++) {
SurfaceId surface_id = MakeSurfaceId(kDisplayFrameSink, i);
aggregator->CallOnSurfaceWillDraw(surface_id);
}
EXPECT_EQ(aggregator->GetActiveCount(), surface_count);
// Aggregate and swap.
aggregator->Aggregate(display_surface_id);
EXPECT_EQ(aggregator->Count(), 0);
aggregator->Swap();
aggregator->SwapHandles();
// Expect 4680 regions:
......@@ -1161,9 +999,9 @@ TEST_F(HitTestAggregatorTest, ExceedLimits) {
EXPECT_EQ(count, 4681u);
}
TEST_F(HitTestAggregatorTest, ActiveRegionCount) {
TEST_F(HitTestAggregatorTest, DiscardedSurfaces) {
TestHitTestAggregator* aggregator = GetAggregator(kDisplayFrameSink);
EXPECT_EQ(aggregator->GetActiveRegionCount(), 0);
EXPECT_EQ(hit_test_manager()->GetRegionCount(), 0);
SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
......@@ -1191,54 +1029,27 @@ TEST_F(HitTestAggregatorTest, ActiveRegionCount) {
c_hit_test_region_list->flags = mojom::kHitTestMine;
c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500);
EXPECT_EQ(aggregator->GetActiveRegionCount(), 0);
EXPECT_EQ(hit_test_manager()->GetRegionCount(), 0);
// Submit in unexpected order.
EXPECT_EQ(aggregator->GetPendingCount(), 0);
aggregator->SubmitHitTestRegionList(c_surface_id,
std::move(c_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 1);
aggregator->SubmitHitTestRegionList(e_surface_id,
std::move(e_hit_test_region_list));
EXPECT_EQ(aggregator->GetPendingCount(), 2);
EXPECT_EQ(aggregator->GetActiveRegionCount(), 0);
// Surfaces added to DisplayFrame in unexpected order.
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetActiveCount(), 0);
aggregator->CallOnSurfaceWillDraw(e_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 1);
EXPECT_EQ(aggregator->GetActiveRegionCount(), 2);
aggregator->CallOnSurfaceWillDraw(c_surface_id);
EXPECT_EQ(aggregator->GetActiveCount(), 2);
EXPECT_EQ(aggregator->GetActiveRegionCount(), 2);
// Aggregate and swap.
hit_test_manager()->SubmitHitTestRegionList(
c_surface_id, 0, std::move(c_hit_test_region_list));
hit_test_manager()->SubmitHitTestRegionList(
e_surface_id, 0, std::move(e_hit_test_region_list));
aggregator->Aggregate(e_surface_id);
EXPECT_EQ(aggregator->Count(), 0);
EXPECT_EQ(aggregator->GetActiveRegionCount(), 2);
aggregator->Swap();
aggregator->SwapHandles();
EXPECT_EQ(aggregator->Count(), 3);
EXPECT_EQ(aggregator->GetActiveRegionCount(), 2);
EXPECT_EQ(hit_test_manager()->GetRegionCount(), 2);
// Discard Surface and ensure active count goes down.
aggregator->CallOnSurfaceDiscarded(c_surface_id);
EXPECT_EQ(aggregator->GetActiveRegionCount(), 2);
hit_test_manager()->CallOnSurfaceDiscarded(c_surface_id);
EXPECT_EQ(hit_test_manager()->GetRegionCount(), 1);
aggregator->CallOnSurfaceDiscarded(e_surface_id);
EXPECT_EQ(aggregator->GetActiveRegionCount(), 0);
hit_test_manager()->CallOnSurfaceDiscarded(e_surface_id);
EXPECT_EQ(hit_test_manager()->GetRegionCount(), 0);
}
} // namespace viz
// 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/service/hit_test/hit_test_aggregator.h"
#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/hit_test/hit_test_aggregator_delegate.h"
namespace viz {
namespace {
// TODO(gklassen): Review and select appropriate sizes based on
// telemetry / UMA.
constexpr uint32_t kMaxRegionsPerSurface = 1024;
} // namespace
HitTestManager::HitTestManager(FrameSinkManagerImpl* frame_sink_manager)
: frame_sink_manager_(frame_sink_manager) {}
HitTestManager::~HitTestManager() = default;
void HitTestManager::SubmitHitTestRegionList(
const SurfaceId& surface_id,
const uint64_t frame_index,
mojom::HitTestRegionListPtr hit_test_region_list) {
if (!ValidateHitTestRegionList(surface_id, hit_test_region_list))
return;
// TODO(gklassen): Runtime validation that hit_test_region_list is valid.
// TODO(gklassen): Inform FrameSink that the hit_test_region_list is invalid.
// TODO(gklassen): FrameSink needs to inform the host of a difficult renderer.
hit_test_region_lists_[surface_id][frame_index] =
std::move(hit_test_region_list);
}
bool HitTestManager::ValidateHitTestRegionList(
const SurfaceId& surface_id,
const mojom::HitTestRegionListPtr& hit_test_region_list) {
if (!hit_test_region_list)
return false;
if (hit_test_region_list->regions.size() > kMaxRegionsPerSurface)
return false;
for (auto& region : hit_test_region_list->regions) {
if (!ValidateHitTestRegion(surface_id, region))
return false;
}
return true;
}
bool HitTestManager::ValidateHitTestRegion(
const SurfaceId& surface_id,
const mojom::HitTestRegionPtr& hit_test_region) {
// If client_id is 0 then use the client_id that
// matches the compositor frame.
if (hit_test_region->frame_sink_id.client_id() == 0) {
hit_test_region->frame_sink_id =
FrameSinkId(surface_id.frame_sink_id().client_id(),
hit_test_region->frame_sink_id.sink_id());
}
// TODO(gklassen): Verify that this client is allowed to submit hit test
// data for the region associated with this |frame_sink_id|.
// TODO(gklassen): Ensure that |region->frame_sink_id| is a child of
// |frame_sink_id|.
if (hit_test_region->flags & mojom::kHitTestChildSurface) {
if (!hit_test_region->local_surface_id.has_value() ||
!hit_test_region->local_surface_id->is_valid()) {
return false;
}
}
return true;
}
bool HitTestManager::OnSurfaceDamaged(const SurfaceId& surface_id,
const BeginFrameAck& ack) {
return false;
}
void HitTestManager::OnSurfaceDiscarded(const SurfaceId& surface_id) {
hit_test_region_lists_.erase(surface_id);
}
void HitTestManager::OnSurfaceActivated(const SurfaceId& surface_id) {
// When a Surface is activated we can confidently remove all
// associated HitTestRegionList objects with an older frame_index.
auto search = hit_test_region_lists_.find(surface_id);
if (search == hit_test_region_lists_.end())
return;
uint64_t frame_index = frame_sink_manager_->GetActiveFrameIndex(surface_id);
auto& frame_index_map = search->second;
for (auto it = frame_index_map.begin(); it != frame_index_map.end();) {
if (it->first != frame_index)
it = frame_index_map.erase(it);
else
++it;
}
}
const mojom::HitTestRegionList* HitTestManager::GetActiveHitTestRegionList(
const SurfaceId& surface_id) const {
auto search = hit_test_region_lists_.find(surface_id);
if (search == hit_test_region_lists_.end())
return nullptr;
uint64_t frame_index = frame_sink_manager_->GetActiveFrameIndex(surface_id);
auto& frame_index_map = search->second;
auto search2 = frame_index_map.find(frame_index);
if (search2 == frame_index_map.end())
return nullptr;
return search2->second.get();
}
} // namespace viz
// 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.
#ifndef COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_MANAGER_H_
#define COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_MANAGER_H_
#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "components/viz/service/surfaces/surface_observer.h"
#include "components/viz/service/viz_service_export.h"
#include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
namespace viz {
class FrameSinkManagerImpl;
// HitTestManager manages the collection of HitTestRegionList objects
// submitted in calls to SubmitCompositorFrame. This collection is
// used by HitTestAggregator.
class VIZ_SERVICE_EXPORT HitTestManager : public SurfaceObserver {
public:
explicit HitTestManager(FrameSinkManagerImpl* frame_sink_manager);
virtual ~HitTestManager();
// Called when HitTestRegionList is submitted along with every call
// to SubmitCompositorFrame.
void SubmitHitTestRegionList(
const SurfaceId& surface_id,
const uint64_t frame_index,
mojom::HitTestRegionListPtr hit_test_region_list);
// Returns the HitTestRegionList corresponding to the given
// surface_id and the active CompositorFrame matched by frame_index.
const mojom::HitTestRegionList* GetActiveHitTestRegionList(
const SurfaceId& surface_id) const;
// SurfaceObserver:
void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override {}
void OnSurfaceActivated(const SurfaceId& surface_id) override;
void OnSurfaceDestroyed(const SurfaceId& surface_id) override {}
bool OnSurfaceDamaged(const SurfaceId& surface_id,
const BeginFrameAck& ack) override;
void OnSurfaceDiscarded(const SurfaceId& surface_id) override;
void OnSurfaceDamageExpected(const SurfaceId& surface_id,
const BeginFrameArgs& args) override {}
void OnSurfaceWillDraw(const SurfaceId& surface_id) override {}
private:
friend class TestHitTestManager;
bool ValidateHitTestRegionList(
const SurfaceId& surface_id,
const mojom::HitTestRegionListPtr& hit_test_region_list);
bool ValidateHitTestRegion(const SurfaceId& surface_id,
const mojom::HitTestRegionPtr& hit_test_region);
FrameSinkManagerImpl* const frame_sink_manager_;
std::map<SurfaceId, base::flat_map<uint64_t, mojom::HitTestRegionListPtr>>
hit_test_region_lists_;
DISALLOW_COPY_AND_ASSIGN(HitTestManager);
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_MANAGER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment