Commit 615f3790 authored by Ria Jiang's avatar Ria Jiang Committed by Commit Bot

Cache referenced RenderPassDrawQuad when creating hit-test data.

A RenderPassDrawQuad can be referenced many times, cache the result
to avoid unnecessary re-computing.

Bug: 947031
Test: viz_unittests
Change-Id: I59c790d3f7e357e5af50c5c780d8078e975ac3cd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1555071Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Commit-Queue: Ria Jiang <riajiang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#652176}
parent 631529ee
......@@ -412,4 +412,158 @@ TEST(HitTestDataProviderDrawQuad, HitTestDataShapeFilters) {
hit_test_region_list_2->regions[0].rect);
}
// Test to ensure that render_pass_list caching works correctly.
TEST(HitTestDataProviderDrawQuad, HitTestDataRenderPassListCache) {
std::unique_ptr<HitTestDataProvider> hit_test_data_provider =
std::make_unique<HitTestDataProviderDrawQuad>(
true /* should_ask_for_child_region */,
true /* root_accepts_events */);
constexpr gfx::Rect frame_rect(1024, 768);
constexpr gfx::Rect child_rect(200, 100);
gfx::Transform invertible_transform;
invertible_transform.Translate(-200, -100);
RenderPassList pass_list;
// A RenderPass that has two SurfaceDrawQuad.
SurfaceId child_surface_id1 = CreateChildSurfaceId(2);
SurfaceId child_surface_id2 = CreateChildSurfaceId(3);
auto pass1 = RenderPass::Create();
pass1->SetNew(1, frame_rect, frame_rect, invertible_transform);
auto* shared_state_1 = pass1->CreateAndAppendSharedQuadState();
shared_state_1->SetAll(invertible_transform, frame_rect, frame_rect,
gfx::RRectF(), frame_rect, false, false, 1,
SkBlendMode::kSrcOver, 0);
auto* surface_quad_1 = pass1->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad_1->SetNew(
pass1->shared_quad_state_list.back(), child_rect, child_rect,
SurfaceRange(child_surface_id1), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false, /*ignores_input_event=*/false);
gfx::Rect child_rect2(400, 400, 100, 100);
auto* surface_quad_2 = pass1->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad_2->SetNew(
pass1->shared_quad_state_list.back(), child_rect2, child_rect2,
SurfaceRange(child_surface_id2), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false, /*ignores_input_event=*/false);
pass_list.push_back(std::move(pass1));
// A RenderPass that has a RenderPassDrawQuad pointing to pass1, a
// SurfaceDrawQuad and a RenderPassDrawQuad pointing to pass1.
auto pass2 = RenderPass::Create();
pass2->SetNew(4, frame_rect, frame_rect, invertible_transform);
auto* shared_state_2 = pass2->CreateAndAppendSharedQuadState();
shared_state_2->SetAll(invertible_transform, frame_rect, frame_rect,
gfx::RRectF(), frame_rect, false, false, 1,
SkBlendMode::kSrcOver, 0);
auto* render_pass_quad_1 =
pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
render_pass_quad_1->SetNew(
pass2->shared_quad_state_list.back(), child_rect, child_rect,
/*render_pass_id=*/1,
/*mask_resource_id=*/0, gfx::RectF(), gfx::Size(), gfx::Vector2dF(1, 1),
gfx::PointF(), gfx::RectF(), false, 1.0f);
SurfaceId child_surface_id3 = CreateChildSurfaceId(4);
gfx::Rect child_rect3(500, 500, 100, 100);
auto* surface_quad_3 = pass2->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad_3->SetNew(
pass2->shared_quad_state_list.back(), child_rect3, child_rect3,
SurfaceRange(child_surface_id3), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false, /*ignores_input_event=*/false);
auto* render_pass_quad_2 =
pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
render_pass_quad_2->SetNew(
pass2->shared_quad_state_list.back(), child_rect2, child_rect2,
/*render_pass_id=*/1,
/*mask_resource_id=*/0, gfx::RectF(), gfx::Size(), gfx::Vector2dF(1, 1),
gfx::PointF(), gfx::RectF(), false, 1.0f);
pass_list.push_back(std::move(pass2));
// The root RenderPass that has three RenderPassDrawQuad point to pass2.
auto pass_root = RenderPass::Create();
pass_root->SetNew(5, frame_rect, frame_rect, invertible_transform);
auto* shared_state_3 = pass_root->CreateAndAppendSharedQuadState();
shared_state_3->SetAll(invertible_transform, frame_rect, frame_rect,
gfx::RRectF(), frame_rect, false, false, 1,
SkBlendMode::kSrcOver, 0);
auto* render_pass_quad_3 =
pass_root->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
render_pass_quad_3->SetNew(
pass_root->shared_quad_state_list.back(), child_rect, child_rect,
/*render_pass_id=*/4,
/*mask_resource_id=*/0, gfx::RectF(), gfx::Size(), gfx::Vector2dF(1, 1),
gfx::PointF(), gfx::RectF(), false, 1.0f);
auto* render_pass_quad_4 =
pass_root->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
render_pass_quad_4->SetNew(
pass_root->shared_quad_state_list.back(), child_rect2, child_rect2,
/*render_pass_id=*/4,
/*mask_resource_id=*/0, gfx::RectF(), gfx::Size(), gfx::Vector2dF(1, 1),
gfx::PointF(), gfx::RectF(), false, 1.0f);
auto* render_pass_quad_5 =
pass_root->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
render_pass_quad_5->SetNew(
pass_root->shared_quad_state_list.back(), child_rect, child_rect,
/*render_pass_id=*/4,
/*mask_resource_id=*/0, gfx::RectF(), gfx::Size(), gfx::Vector2dF(1, 10),
gfx::PointF(), gfx::RectF(), false, 1.0f);
pass_list.push_back(std::move(pass_root));
CompositorFrame compositor_frame =
CompositorFrameBuilder().SetRenderPassList(std::move(pass_list)).Build();
base::Optional<HitTestRegionList> hit_test_region_list =
hit_test_data_provider->GetHitTestData(compositor_frame);
// We should have the three SurfaceDrawQuad associated HitTestRegion, repeated
// based on RenderPassDrawQuad.
EXPECT_EQ(15u, hit_test_region_list->regions.size());
for (size_t i = 0; i < 15; i += 5) {
EXPECT_EQ(child_surface_id1.frame_sink_id(),
hit_test_region_list->regions[i].frame_sink_id);
EXPECT_EQ(HitTestRegionFlags::kHitTestMouse |
HitTestRegionFlags::kHitTestTouch |
HitTestRegionFlags::kHitTestChildSurface |
HitTestRegionFlags::kHitTestAsk,
hit_test_region_list->regions[i].flags);
EXPECT_EQ(child_rect, hit_test_region_list->regions[i].rect);
EXPECT_EQ(child_surface_id2.frame_sink_id(),
hit_test_region_list->regions[i + 1].frame_sink_id);
EXPECT_EQ(HitTestRegionFlags::kHitTestMouse |
HitTestRegionFlags::kHitTestTouch |
HitTestRegionFlags::kHitTestChildSurface |
HitTestRegionFlags::kHitTestAsk,
hit_test_region_list->regions[i + 1].flags);
EXPECT_EQ(child_rect2, hit_test_region_list->regions[i + 1].rect);
EXPECT_EQ(child_surface_id3.frame_sink_id(),
hit_test_region_list->regions[i + 2].frame_sink_id);
EXPECT_EQ(HitTestRegionFlags::kHitTestMouse |
HitTestRegionFlags::kHitTestTouch |
HitTestRegionFlags::kHitTestChildSurface |
HitTestRegionFlags::kHitTestAsk,
hit_test_region_list->regions[i + 2].flags);
EXPECT_EQ(child_rect3, hit_test_region_list->regions[i + 2].rect);
EXPECT_EQ(child_surface_id1.frame_sink_id(),
hit_test_region_list->regions[i + 3].frame_sink_id);
EXPECT_EQ(HitTestRegionFlags::kHitTestMouse |
HitTestRegionFlags::kHitTestTouch |
HitTestRegionFlags::kHitTestChildSurface |
HitTestRegionFlags::kHitTestAsk,
hit_test_region_list->regions[i + 3].flags);
EXPECT_EQ(child_rect, hit_test_region_list->regions[i + 3].rect);
EXPECT_EQ(child_surface_id2.frame_sink_id(),
hit_test_region_list->regions[i + 4].frame_sink_id);
EXPECT_EQ(HitTestRegionFlags::kHitTestMouse |
HitTestRegionFlags::kHitTestTouch |
HitTestRegionFlags::kHitTestChildSurface |
HitTestRegionFlags::kHitTestAsk,
hit_test_region_list->regions[i + 4].flags);
EXPECT_EQ(child_rect2, hit_test_region_list->regions[i + 4].rect);
}
}
} // namespace viz
......@@ -81,10 +81,25 @@ std::vector<gfx::Rect> ExtractAlphaRects(
return filter_regions;
}
void AddHitTestDataFromRenderPass(const CompositorFrame& frame,
RenderPassId render_pass_id,
std::vector<HitTestRegion>* regions,
bool should_ask_for_child_region) {
void AddHitTestDataFromRenderPass(
const CompositorFrame& frame,
RenderPassId render_pass_id,
std::vector<HitTestRegion>* regions,
bool should_ask_for_child_region,
base::flat_map<RenderPassId, std::pair<uint32_t, uint32_t>>*
render_pass_hit_test_region_list) {
if (render_pass_hit_test_region_list->count(render_pass_id)) {
const auto& list_range =
render_pass_hit_test_region_list->find(render_pass_id)->second;
const uint32_t start = list_range.first;
const uint32_t end = list_range.second;
if (start >= end || regions->size() < end)
return;
regions->insert(regions->end(), regions->begin() + start,
regions->begin() + end);
return;
}
const RenderPass* render_pass = GetRenderPassInFrame(frame, render_pass_id);
if (!render_pass)
return;
......@@ -99,6 +114,7 @@ void AddHitTestDataFromRenderPass(const CompositorFrame& frame,
return;
}
const uint32_t render_pass_hit_test_region_list_start = regions->size();
for (const DrawQuad* quad : render_pass->quad_list) {
if (quad->material == DrawQuad::SURFACE_CONTENT) {
const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
......@@ -139,9 +155,14 @@ void AddHitTestDataFromRenderPass(const CompositorFrame& frame,
const RenderPassDrawQuad* render_quad =
RenderPassDrawQuad::MaterialCast(quad);
AddHitTestDataFromRenderPass(frame, render_quad->render_pass_id, regions,
should_ask_for_child_region);
should_ask_for_child_region,
render_pass_hit_test_region_list);
}
}
const uint32_t render_pass_hit_test_region_list_end = regions->size();
render_pass_hit_test_region_list->emplace(
render_pass_id, std::make_pair(render_pass_hit_test_region_list_start,
render_pass_hit_test_region_list_end));
}
} // namespace
......@@ -157,9 +178,12 @@ base::Optional<HitTestRegionList> HitTestDataBuilder::CreateHitTestData(
: HitTestRegionFlags::kHitTestIgnore) |
HitTestRegionFlags::kHitTestMouse | HitTestRegionFlags::kHitTestTouch;
hit_test_region_list->bounds.set_size(compositor_frame.size_in_pixels());
base::flat_map<RenderPassId, std::pair<uint32_t, uint32_t>>
render_pass_hit_test_region_list_cache;
AddHitTestDataFromRenderPass(
compositor_frame, compositor_frame.render_pass_list.back()->id,
&hit_test_region_list->regions, should_ask_for_child_region);
&hit_test_region_list->regions, should_ask_for_child_region,
&render_pass_hit_test_region_list_cache);
return hit_test_region_list;
}
......
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