Commit ebaf9341 authored by sunxd's avatar sunxd Committed by Commit Bot

cc: Ignore invisible RPDQs when tiling mask layers

When tiling masks, sometimes we get tiles that are completely outside
the layer's visible rect. This would lead to problems in determining
whether quad rect contains visible rect, because an empty rect's origin
is not always contained by a quad rect that locates at a random origin.

This would result in problems when converting draw quads to RPDQs in
IPC, thus breaking Android WebView.

This CL makes RenderSurfaceImpl::TileMaskLayer throw away such quads.

Bug: 740810
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I07c4024894740d09ba4708d5ead37a4bec99d7ea
Reviewed-on: https://chromium-review.googlesource.com/570630Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Commit-Queue: Xianda Sun <sunxd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491082}
parent 0c548f41
......@@ -474,8 +474,8 @@ void RenderSurfaceImpl::TileMaskLayer(RenderPass* render_pass,
1.f / mask_quad_to_surface_contents_scale.y());
shared_quad_state->visible_quad_layer_rect =
gfx::ScaleToEnclosingRect(shared_quad_state->visible_quad_layer_rect,
mask_quad_to_surface_contents_scale.x(),
mask_quad_to_surface_contents_scale.y());
1.f / mask_quad_to_surface_contents_scale.x(),
1.f / mask_quad_to_surface_contents_scale.y());
gfx::Rect content_rect_in_coverage_space = gfx::ScaleToEnclosingRect(
content_rect(), 1.f / mask_quad_to_surface_contents_scale.x(),
1.f / mask_quad_to_surface_contents_scale.y());
......@@ -485,11 +485,16 @@ void RenderSurfaceImpl::TileMaskLayer(RenderPass* render_pass,
for (auto* temp_quad : temp_render_pass->quad_list) {
gfx::Rect quad_rect = temp_quad->rect;
gfx::Rect render_quad_rect = quad_rect;
if (!quad_rect.Intersects(content_rect_in_coverage_space))
continue;
render_quad_rect =
gfx::Rect render_quad_rect =
gfx::IntersectRects(quad_rect, content_rect_in_coverage_space);
gfx::Rect quad_visible_rect_in_coverage_space = gfx::IntersectRects(
render_quad_rect, visible_layer_rect_in_coverage_space);
if (quad_visible_rect_in_coverage_space.IsEmpty())
continue;
gfx::RectF quad_rect_in_surface_contents_space = gfx::ScaleRect(
gfx::RectF(render_quad_rect), mask_quad_to_surface_contents_scale.x(),
mask_quad_to_surface_contents_scale.y());
......@@ -501,9 +506,6 @@ void RenderSurfaceImpl::TileMaskLayer(RenderPass* render_pass,
switch (temp_quad->material) {
case DrawQuad::TILED_CONTENT: {
DCHECK_EQ(1U, temp_quad->resources.count);
RenderPassDrawQuad* quad =
render_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
gfx::Size mask_texture_size =
static_cast<ContentDrawQuadBase*>(temp_quad)->texture_size;
gfx::RectF temp_tex_coord_rect =
......@@ -520,10 +522,11 @@ void RenderSurfaceImpl::TileMaskLayer(RenderPass* render_pass,
gfx::RectF mask_uv_rect = gfx::RectF(render_quad_rect);
coverage_to_normalized_mask.TransformRect(&mask_uv_rect);
RenderPassDrawQuad* quad =
render_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
quad->SetNew(shared_quad_state, render_quad_rect,
gfx::IntersectRects(temp_quad->visible_rect,
visible_layer_rect_in_coverage_space),
id(), temp_quad->resources.ids[0], mask_uv_rect,
quad_visible_rect_in_coverage_space, id(),
temp_quad->resources.ids[0], mask_uv_rect,
mask_texture_size, owning_layer_to_surface_contents_scale,
FiltersOrigin(),
quad_rect_in_non_normalized_texture_space);
......@@ -535,13 +538,13 @@ void RenderSurfaceImpl::TileMaskLayer(RenderPass* render_pass,
DCHECK_EQ(
SkColorGetA(static_cast<SolidColorDrawQuad*>(temp_quad)->color),
solid);
RenderPassDrawQuad* quad =
render_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
quad->SetNew(shared_quad_state, render_quad_rect,
gfx::IntersectRects(temp_quad->visible_rect,
visible_layer_rect_in_coverage_space),
id(), 0, gfx::RectF(), gfx::Size(),
owning_layer_to_surface_contents_scale, FiltersOrigin(),
quad_visible_rect_in_coverage_space, id(), 0, gfx::RectF(),
gfx::Size(), owning_layer_to_surface_contents_scale,
FiltersOrigin(),
quad_rect_in_non_normalized_texture_space);
} break;
case DrawQuad::DEBUG_BORDER:
......
......@@ -6,9 +6,11 @@
#include "cc/layers/layer_impl.h"
#include "cc/layers/render_surface_impl.h"
#include "cc/quads/shared_quad_state.h"
#include "cc/quads/tile_draw_quad.h"
#include "cc/test/fake_impl_task_runner_provider.h"
#include "cc/test/fake_layer_tree_frame_sink.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_picture_layer_impl.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/test/layer_test_common.h"
#include "cc/test/mock_occlusion_tracker.h"
......@@ -32,6 +34,52 @@ namespace {
code_to_test; \
EXPECT_FALSE(render_surface->SurfacePropertyChanged())
// The AppendQuads method of this class generates multiple quads and one of them
// does not intersect with visible_layer_rect.
class FakePictureLayerImplForRenderSurfaceTest : public FakePictureLayerImpl {
public:
static std::unique_ptr<FakePictureLayerImplForRenderSurfaceTest> CreateMask(
LayerTreeImpl* tree_impl,
int id) {
return base::WrapUnique(
new FakePictureLayerImplForRenderSurfaceTest(tree_impl, id));
}
std::unique_ptr<LayerImpl> CreateLayerImpl(
LayerTreeImpl* tree_impl) override {
return base::WrapUnique(
new FakePictureLayerImplForRenderSurfaceTest(tree_impl, id()));
}
void SetQuadRectsForTesting(std::vector<gfx::Rect> quad_rects) {
quad_rects_ = quad_rects;
}
bool HasValidTilePriorities() const override { return false; }
void AppendQuads(RenderPass* render_pass,
AppendQuadsData* append_quads_data) override {
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
float max_contents_scale = 1.f;
PopulateScaledSharedQuadState(shared_quad_state, max_contents_scale,
max_contents_scale);
for (const auto& rect : quad_rects_) {
TileDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
quad->SetNew(shared_quad_state, rect, rect, rect, 0, gfx::RectF(rect),
bounds(), false, false);
}
}
protected:
FakePictureLayerImplForRenderSurfaceTest(LayerTreeImpl* tree_impl, int id)
: FakePictureLayerImpl(tree_impl,
id,
Layer::LayerMaskType::MULTI_TEXTURE_MASK) {}
std::vector<gfx::Rect> quad_rects_;
};
TEST(RenderSurfaceTest, VerifySurfaceChangesAreTrackedProperly) {
//
// This test checks that SurfacePropertyChanged() has the correct behavior.
......@@ -150,7 +198,6 @@ TEST(RenderSurfaceTest, SanityCheckSurfaceCreatesCorrectSharedQuadState) {
EXPECT_EQ(blend_mode, shared_quad_state->blend_mode);
}
TEST(RenderSurfaceTest, SanityCheckSurfaceCreatesCorrectRenderPass) {
FakeImplTaskRunnerProvider task_runner_provider;
TestTaskGraphRunner task_graph_runner;
......@@ -191,5 +238,72 @@ TEST(RenderSurfaceTest, SanityCheckSurfaceCreatesCorrectRenderPass) {
EXPECT_EQ(origin, pass->transform_to_root_target);
}
TEST(RenderSurfaceTest, SanityCheckSurfaceDropsOccludedRenderPassDrawQuads) {
FakeImplTaskRunnerProvider task_runner_provider;
TestTaskGraphRunner task_graph_runner;
std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink =
FakeLayerTreeFrameSink::Create3d();
FakeLayerTreeHostImpl host_impl(&task_runner_provider, &task_graph_runner);
std::unique_ptr<LayerImpl> root_layer =
LayerImpl::Create(host_impl.active_tree(), 1);
int owning_layer_id = 2;
std::unique_ptr<LayerImpl> owning_layer =
LayerImpl::Create(host_impl.active_tree(), owning_layer_id);
int mask_layer_id = 3;
std::unique_ptr<FakePictureLayerImplForRenderSurfaceTest> mask_layer =
FakePictureLayerImplForRenderSurfaceTest::CreateMask(
host_impl.active_tree(), mask_layer_id);
mask_layer->SetBounds(gfx::Size(200, 100));
mask_layer->SetDrawsContent(true);
std::vector<gfx::Rect> quad_rects;
quad_rects.push_back(gfx::Rect(0, 0, 100, 100));
quad_rects.push_back(gfx::Rect(100, 0, 100, 100));
mask_layer->SetQuadRectsForTesting(quad_rects);
owning_layer->SetBounds(gfx::Size(200, 100));
owning_layer->SetDrawsContent(true);
owning_layer->test_properties()->SetMaskLayer(std::move(mask_layer));
root_layer->test_properties()->AddChild(std::move(owning_layer));
host_impl.active_tree()->SetRootLayerForTesting(std::move(root_layer));
host_impl.SetVisible(true);
host_impl.InitializeRenderer(layer_tree_frame_sink.get());
host_impl.active_tree()->BuildLayerListAndPropertyTreesForTesting();
host_impl.active_tree()->UpdateDrawProperties();
ASSERT_TRUE(
GetRenderSurface(host_impl.active_tree()->LayerById(owning_layer_id)));
RenderSurfaceImpl* render_surface =
GetRenderSurface(host_impl.active_tree()->LayerById(owning_layer_id));
gfx::Rect content_rect(0, 0, 200, 100);
gfx::Rect occluded(0, 0, 100, 100);
render_surface->SetContentRectForTesting(content_rect);
render_surface->set_occlusion_in_content_space(
Occlusion(gfx::Transform(), SimpleEnclosedRegion(occluded),
SimpleEnclosedRegion(occluded)));
std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData append_quads_data;
render_surface->AppendQuads(DRAW_MODE_HARDWARE, render_pass.get(),
&append_quads_data);
ASSERT_EQ(1u, render_pass->shared_quad_state_list.size());
SharedQuadState* shared_quad_state =
render_pass->shared_quad_state_list.front();
EXPECT_EQ(content_rect,
gfx::Rect(shared_quad_state->visible_quad_layer_rect));
// The quad (0, 0, 100, 100) is occluded and should be dropped.
ASSERT_EQ(1u, render_pass->quad_list.size());
EXPECT_EQ(gfx::Rect(100, 0, 100, 100).ToString(),
render_pass->quad_list.front()->rect.ToString());
}
} // namespace
} // namespace cc
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