#include "cc/layers/tile_based_layer_impl.h"
#include <memory>
#include <utility>
#include <vector>
#include "base/check_deref.h"
#include "cc/debug/layer_tree_debug_state.h"
#include "cc/layers/append_quads_context.h"
#include "cc/layers/append_quads_data.h"
#include "cc/test/layer_test_common.h"
#include "cc/test/test_layer_tree_host_base.h"
#include "cc/tiles/tile_draw_info.h"
#include "cc/tiles/tile_priority.h"
#include "cc/tiles/tiling_coverage_iterator.h"
#include "cc/tiles/tiling_set_coverage_iterator.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
namespace {
class FakeTile {
public:
FakeTile() = default;
~FakeTile() = default;
TileDrawInfo::Mode draw_mode() { return TileDrawInfo::SOLID_COLOR_MODE; }
bool IsReadyToDraw() const { return true; }
};
class FakeTilingCoverageIterator;
class FakeTiling {
public:
using Tile = FakeTile;
using CoverageIterator = FakeTilingCoverageIterator;
FakeTiling() = default;
~FakeTiling() = default;
CoverageIterator Cover(const gfx::Rect& coverage_rect,
float coverage_scale) const;
Tile* TileAt(const TileIndex& index) const { return nullptr; }
float contents_scale_key() const { return 1.0f; }
const TilingData* tiling_data() const { return nullptr; }
gfx::Size raster_size() const { return gfx::Size{100, 100}; }
const gfx::AxisTransform2d& raster_transform() const {
return raster_transform_;
}
private:
gfx::AxisTransform2d raster_transform_;
};
class FakeTilingCoverageIterator : public TilingCoverageIterator<FakeTiling> {
public:
using TilingCoverageIterator<FakeTiling>::TilingCoverageIterator;
};
class TestTileBasedLayerImpl : public TileBasedLayerImpl<FakeTiling> {
public:
TestTileBasedLayerImpl(LayerTreeImpl* tree_impl, int id)
: TileBasedLayerImpl<FakeTiling>(tree_impl, id) {}
private:
void AppendQuadsSpecialization(const AppendQuadsContext& context,
viz::CompositorRenderPass* render_pass,
AppendQuadsData* append_quads_data,
viz::SharedQuadState* shared_quad_state,
const Occlusion& scaled_occlusion,
const gfx::Vector2d& quad_offset) override {}
float GetMaximumContentsScaleForUseInAppendQuads() override { return 1.f; }
bool IsDirectlyCompositedImage() const override { return false; }
TilingResolution GetTilingResolutionForDebugBorders(
const FakeTiling* tiling) const override {
return TilingResolution::kHigh;
}
void AppendQuadsForResourcelessSoftwareDraw(
const AppendQuadsContext& context,
viz::CompositorRenderPass* render_pass,
AppendQuadsData* append_quads_data,
viz::SharedQuadState* shared_quad_state,
const Occlusion& scaled_occlusion) override {}
TilingSetCoverageIterator<FakeTiling> Cover(
const gfx::Rect& coverage_rect,
float coverage_scale,
float ideal_contents_scale) override {
return TilingSetCoverageIterator<FakeTiling>(
empty_tilings_, coverage_rect, coverage_scale, ideal_contents_scale);
}
float GetIdealContentsScaleKey() const override { return 1.f; }
std::vector<std::unique_ptr<FakeTiling>> empty_tilings_;
};
FakeTiling::CoverageIterator FakeTiling::Cover(const gfx::Rect& coverage_rect,
float coverage_scale) const {
return CoverageIterator();
}
class TileBasedLayerImplTest : public TestLayerTreeHostBase {};
TEST_F(TileBasedLayerImplTest, IsBackdropFilterMask_DefaultsToFalse) {
auto layer = std::make_unique<TestTileBasedLayerImpl>(
host_impl()->active_tree(), 1);
EXPECT_FALSE(layer->is_backdrop_filter_mask());
}
TEST_F(TileBasedLayerImplTest, SetIsBackdropFilterMask_GetterReflectsSetter) {
auto layer = std::make_unique<TestTileBasedLayerImpl>(
host_impl()->active_tree(), 1);
layer->SetIsBackdropFilterMask(true);
EXPECT_TRUE(layer->is_backdrop_filter_mask());
layer->SetIsBackdropFilterMask(false);
EXPECT_FALSE(layer->is_backdrop_filter_mask());
}
TEST_F(TileBasedLayerImplTest, SetIsBackdropFilterMask_RedundantCalls) {
auto layer = std::make_unique<TestTileBasedLayerImpl>(
host_impl()->active_tree(), 1);
layer->SetIsBackdropFilterMask(true);
EXPECT_TRUE(layer->is_backdrop_filter_mask());
layer->SetIsBackdropFilterMask(true);
EXPECT_TRUE(layer->is_backdrop_filter_mask());
layer->SetIsBackdropFilterMask(false);
EXPECT_FALSE(layer->is_backdrop_filter_mask());
layer->SetIsBackdropFilterMask(false);
EXPECT_FALSE(layer->is_backdrop_filter_mask());
}
TEST_F(TileBasedLayerImplTest,
SetIsBackdropFilterMask_CallsSetNeedsPushProperties) {
SetupPendingTree();
auto layer = std::make_unique<TestTileBasedLayerImpl>(
host_impl()->pending_tree(), 42);
auto* raw_layer = layer.get();
host_impl()->pending_tree()->AddLayer(std::move(layer));
host_impl()->pending_tree()->ClearLayersThatShouldPushProperties();
raw_layer->ResetChangeTracking();
raw_layer->SetIsBackdropFilterMask(true);
const auto& layers =
host_impl()->pending_tree()->LayersThatShouldPushProperties();
ASSERT_EQ(layers.size(), 1u);
EXPECT_NE(layers.find(raw_layer), layers.end());
}
TEST_F(
TileBasedLayerImplTest,
SetIsBackdropFilterMask_DoesNotCallSetNeedsPushPropertiesIfValueUnchanged) {
SetupPendingTree();
auto layer = std::make_unique<TestTileBasedLayerImpl>(
host_impl()->pending_tree(), 42);
auto* raw_layer = layer.get();
host_impl()->pending_tree()->AddLayer(std::move(layer));
host_impl()->pending_tree()->ClearLayersThatShouldPushProperties();
raw_layer->ResetChangeTracking();
raw_layer->SetIsBackdropFilterMask(false);
const auto& layers =
host_impl()->pending_tree()->LayersThatShouldPushProperties();
EXPECT_EQ(layers.size(), 0u);
}
TEST_F(TileBasedLayerImplTest,
AppendQuadsDoesNotAppendQuadsForBackdropFilterMask) {
constexpr gfx::Size kLayerBounds(1300, 1900);
constexpr gfx::Rect kLayerRect(kLayerBounds);
constexpr float kOpacity = 1.0;
auto layer = std::make_unique<TestTileBasedLayerImpl>(
host_impl()->active_tree(), 42);
auto* raw_layer = layer.get();
host_impl()->active_tree()->AddLayer(std::move(layer));
raw_layer->SetIsBackdropFilterMask(true);
raw_layer->SetBounds(kLayerBounds);
raw_layer->draw_properties().visible_layer_rect = kLayerRect;
raw_layer->draw_properties().opacity = kOpacity;
SetupRootProperties(host_impl()->active_tree()->root_layer());
auto render_pass = viz::CompositorRenderPass::Create();
AppendQuadsData data;
raw_layer->AppendQuads(AppendQuadsContext{DRAW_MODE_SOFTWARE, {}, false},
render_pass.get(), &data);
EXPECT_EQ(render_pass->quad_list.size(), 0u);
}
TEST_F(TileBasedLayerImplTest,
AppendQuadsDoesNotAppendQuadsForBackdropFilterMaskWithSolidColor) {
constexpr gfx::Size kLayerBounds(1300, 1900);
constexpr gfx::Rect kLayerRect(kLayerBounds);
constexpr SkColor4f kLayerColor = SkColors::kRed;
constexpr float kOpacity = 1.0;
auto layer = std::make_unique<TestTileBasedLayerImpl>(
host_impl()->active_tree(), 42);
auto* raw_layer = layer.get();
host_impl()->active_tree()->AddLayer(std::move(layer));
raw_layer->SetIsBackdropFilterMask(true);
raw_layer->SetSolidColor(kLayerColor);
raw_layer->SetBounds(kLayerBounds);
raw_layer->draw_properties().visible_layer_rect = kLayerRect;
raw_layer->draw_properties().opacity = kOpacity;
SetupRootProperties(host_impl()->active_tree()->root_layer());
auto render_pass = viz::CompositorRenderPass::Create();
AppendQuadsData data;
raw_layer->AppendQuads(AppendQuadsContext{DRAW_MODE_SOFTWARE, {}, false},
render_pass.get(), &data);
EXPECT_EQ(render_pass->quad_list.size(), 0u);
}
TEST_F(TileBasedLayerImplTest, SettingSolidColorResultsInSolidColorQuad) {
constexpr gfx::Size kLayerBounds(1300, 1900);
constexpr gfx::Rect kLayerRect(kLayerBounds);
constexpr SkColor4f kLayerColor = SkColors::kRed;
constexpr float kOpacity = 1.0;
auto layer = std::make_unique<TestTileBasedLayerImpl>(
host_impl()->active_tree(), 42);
auto* raw_layer = layer.get();
host_impl()->active_tree()->AddLayer(std::move(layer));
raw_layer->SetSolidColor(kLayerColor);
raw_layer->SetBounds(kLayerBounds);
raw_layer->draw_properties().visible_layer_rect = kLayerRect;
raw_layer->draw_properties().opacity = kOpacity;
SetupRootProperties(host_impl()->active_tree()->root_layer());
auto render_pass = viz::CompositorRenderPass::Create();
AppendQuadsData data;
raw_layer->AppendQuads(AppendQuadsContext{DRAW_MODE_SOFTWARE, {}, false},
render_pass.get(), &data);
EXPECT_EQ(render_pass->quad_list.size(), 1u);
EXPECT_EQ(render_pass->quad_list.front()->rect, kLayerRect);
EXPECT_EQ(render_pass->quad_list.front()->visible_rect, kLayerRect);
EXPECT_EQ(render_pass->quad_list.front()->shared_quad_state->opacity,
kOpacity);
EXPECT_EQ(render_pass->quad_list.front()->material,
viz::DrawQuad::Material::kSolidColor);
EXPECT_EQ(
viz::SolidColorDrawQuad::MaterialCast(render_pass->quad_list.front())
->color,
kLayerColor);
}
TEST_F(TileBasedLayerImplTest, AppendQuadsAppendsDebugBorders) {
LayerTreeDebugState debug_state;
debug_state.show_debug_borders.set(DebugBorderType::LAYER);
host_impl()->SetDebugState(debug_state);
auto layer = std::make_unique<TestTileBasedLayerImpl>(
host_impl()->active_tree(), 42);
auto* raw_layer = layer.get();
host_impl()->active_tree()->AddLayer(std::move(layer));
SetupRootProperties(host_impl()->active_tree()->root_layer());
auto render_pass = viz::CompositorRenderPass::Create();
AppendQuadsData data;
raw_layer->AppendQuads(AppendQuadsContext{DRAW_MODE_SOFTWARE, {}, false},
render_pass.get(), &data);
EXPECT_EQ(render_pass->quad_list.size(), 1u);
EXPECT_EQ(render_pass->quad_list.front()->material,
viz::DrawQuad::Material::kDebugBorder);
}
TEST_F(TileBasedLayerImplTest,
AppendQuadsDoesNotSetClipRectWhenNotDirectlyCompositedImage) {
constexpr gfx::Size kLayerBounds(100, 200);
constexpr gfx::Rect kLayerRect(kLayerBounds);
auto layer = std::make_unique<TestTileBasedLayerImpl>(
host_impl()->active_tree(), 1);
auto* raw_layer = layer.get();
host_impl()->active_tree()->AddLayer(std::move(layer));
raw_layer->SetBounds(kLayerBounds);
raw_layer->draw_properties().visible_layer_rect = kLayerRect;
SetupRootProperties(host_impl()->active_tree()->root_layer());
auto render_pass = viz::CompositorRenderPass::Create();
AppendQuadsData data;
raw_layer->AppendQuads(AppendQuadsContext{DRAW_MODE_SOFTWARE, {}, false},
render_pass.get(), &data);
ASSERT_EQ(render_pass->shared_quad_state_list.size(), 1u);
EXPECT_FALSE(render_pass->shared_quad_state_list.front()->clip_rect);
}
class DirectlyCompositedTileBasedLayerImpl : public TestTileBasedLayerImpl {
public:
DirectlyCompositedTileBasedLayerImpl(LayerTreeImpl* tree_impl, int id)
: TestTileBasedLayerImpl(tree_impl, id) {}
private:
bool IsDirectlyCompositedImage() const override { return true; }
float GetIdealContentsScaleKey() const override { return 1.f; }
};
TEST_F(TileBasedLayerImplTest,
AppendQuadsSetsClipRectForDirectlyCompositedImage) {
constexpr gfx::Size kLayerBounds(100, 200);
constexpr gfx::Rect kLayerRect(kLayerBounds);
auto layer = std::make_unique<DirectlyCompositedTileBasedLayerImpl>(
host_impl()->active_tree(), 1);
auto* raw_layer = layer.get();
host_impl()->active_tree()->AddLayer(std::move(layer));
raw_layer->SetBounds(kLayerBounds);
raw_layer->draw_properties().visible_layer_rect = kLayerRect;
SetupRootProperties(host_impl()->active_tree()->root_layer());
auto render_pass = viz::CompositorRenderPass::Create();
AppendQuadsData data;
raw_layer->AppendQuads(AppendQuadsContext{DRAW_MODE_SOFTWARE, {}, false},
render_pass.get(), &data);
ASSERT_EQ(render_pass->shared_quad_state_list.size(), 1u);
EXPECT_EQ(render_pass->shared_quad_state_list.front()->clip_rect, kLayerRect);
}
class OcclusionTestTileBasedLayerImpl : public TestTileBasedLayerImpl {
public:
OcclusionTestTileBasedLayerImpl(LayerTreeImpl* tree_impl, int id)
: TestTileBasedLayerImpl(tree_impl, id) {}
const Occlusion& scaled_occlusion() const { return scaled_occlusion_; }
void set_max_contents_scale(float scale) { max_contents_scale_ = scale; }
private:
void AppendQuadsSpecialization(const AppendQuadsContext& context,
viz::CompositorRenderPass* render_pass,
AppendQuadsData* append_quads_data,
viz::SharedQuadState* shared_quad_state,
const Occlusion& scaled_occlusion,
const gfx::Vector2d& quad_offset) override {
scaled_occlusion_ = scaled_occlusion;
auto* quad =
render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
quad->SetNew(shared_quad_state, gfx::Rect(1, 1), gfx::Rect(1, 1),
SkColors::kTransparent, false);
}
float GetMaximumContentsScaleForUseInAppendQuads() override {
return max_contents_scale_;
}
float GetIdealContentsScaleKey() const override { return 1.f; }
Occlusion scaled_occlusion_;
float max_contents_scale_ = 1.f;
};
class ResourcelessSoftwareDrawTileBasedLayerImpl
: public TestTileBasedLayerImpl {
public:
ResourcelessSoftwareDrawTileBasedLayerImpl(LayerTreeImpl* tree_impl, int id)
: TestTileBasedLayerImpl(tree_impl, id) {}
bool append_quads_for_resourceless_software_draw_called() const {
return append_quads_for_resourceless_software_draw_called_;
}
private:
void AppendQuadsForResourcelessSoftwareDraw(
const AppendQuadsContext& context,
viz::CompositorRenderPass* render_pass,
AppendQuadsData* append_quads_data,
viz::SharedQuadState* shared_quad_state,
const Occlusion& scaled_occlusion) override {
append_quads_for_resourceless_software_draw_called_ = true;
auto* quad =
render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
quad->SetNew(shared_quad_state, gfx::Rect(1, 1), gfx::Rect(1, 1),
SkColors::kTransparent, false);
}
float GetIdealContentsScaleKey() const override { return 1.f; }
bool append_quads_for_resourceless_software_draw_called_ = false;
};
TEST_F(TileBasedLayerImplTest, AppendQuadsScalesOcclusion) {
const float scale = 2.0f;
const gfx::Rect layer_rect(0, 0, 10, 10);
const gfx::Rect occluded_rect_in_content_space(0, 0, 5, 10);
auto layer = std::make_unique<OcclusionTestTileBasedLayerImpl>(
host_impl()->active_tree(), 1);
auto* raw_layer = layer.get();
host_impl()->active_tree()->AddLayer(std::move(layer));
raw_layer->set_max_contents_scale(scale);
raw_layer->SetBounds(layer_rect.size());
raw_layer->draw_properties().visible_layer_rect = layer_rect;
gfx::Transform screen_space_transform;
screen_space_transform.Scale(scale, scale);
raw_layer->draw_properties().screen_space_transform = screen_space_transform;
raw_layer->draw_properties().occlusion_in_content_space = Occlusion(
gfx::Transform(), SimpleEnclosedRegion(occluded_rect_in_content_space),
SimpleEnclosedRegion());
SetupRootProperties(host_impl()->active_tree()->root_layer());
auto render_pass = viz::CompositorRenderPass::Create();
AppendQuadsData data;
raw_layer->AppendQuads(AppendQuadsContext{DRAW_MODE_SOFTWARE, {}, true},
render_pass.get(), &data);
const gfx::Rect expected_occluded_rect =
gfx::ScaleToEnclosingRect(occluded_rect_in_content_space, scale);
auto enclosing_rect = gfx::ScaleToEnclosingRect(layer_rect, scale);
EXPECT_EQ(
raw_layer->scaled_occlusion().GetUnoccludedContentRect(enclosing_rect),
gfx::SubtractRects(enclosing_rect, expected_occluded_rect));
}
TEST_F(TileBasedLayerImplTest,
AppendQuadsInvokesAppendQuadsForResourcelessSoftwareDraw) {
constexpr gfx::Size kLayerBounds(100, 200);
constexpr gfx::Rect kLayerRect(kLayerBounds);
auto layer = std::make_unique<ResourcelessSoftwareDrawTileBasedLayerImpl>(
host_impl()->active_tree(), 1);
auto* raw_layer = layer.get();
host_impl()->active_tree()->AddLayer(std::move(layer));
raw_layer->SetBounds(kLayerBounds);
raw_layer->draw_properties().visible_layer_rect = kLayerRect;
SetupRootProperties(host_impl()->active_tree()->root_layer());
auto render_pass = viz::CompositorRenderPass::Create();
AppendQuadsData data;
raw_layer->AppendQuads(
AppendQuadsContext{DRAW_MODE_RESOURCELESS_SOFTWARE, {}, false},
render_pass.get(), &data);
EXPECT_TRUE(raw_layer->append_quads_for_resourceless_software_draw_called());
}
TEST_F(
TileBasedLayerImplTest,
AppendQuadsDoesNotInvokeAppendQuadsForResourcelessSoftwareDrawWhenNotExpected) {
constexpr gfx::Size kLayerBounds(100, 200);
constexpr gfx::Rect kLayerRect(kLayerBounds);
auto layer = std::make_unique<ResourcelessSoftwareDrawTileBasedLayerImpl>(
host_impl()->active_tree(), 1);
auto* raw_layer = layer.get();
host_impl()->active_tree()->AddLayer(std::move(layer));
raw_layer->SetBounds(kLayerBounds);
raw_layer->draw_properties().visible_layer_rect = kLayerRect;
SetupRootProperties(host_impl()->active_tree()->root_layer());
auto render_pass = viz::CompositorRenderPass::Create();
AppendQuadsData data;
raw_layer->AppendQuads(AppendQuadsContext{DRAW_MODE_SOFTWARE, {}, false},
render_pass.get(), &data);
EXPECT_FALSE(raw_layer->append_quads_for_resourceless_software_draw_called());
}
class QuadOffsetTestTileBasedLayerImpl : public TestTileBasedLayerImpl {
public:
QuadOffsetTestTileBasedLayerImpl(LayerTreeImpl* tree_impl, int id)
: TestTileBasedLayerImpl(tree_impl, id) {}
const gfx::Vector2d& quad_offset() const { return quad_offset_; }
private:
void AppendQuadsSpecialization(const AppendQuadsContext& context,
viz::CompositorRenderPass* render_pass,
AppendQuadsData* append_quads_data,
viz::SharedQuadState* shared_quad_state,
const Occlusion& scaled_occlusion,
const gfx::Vector2d& quad_offset) override {
quad_offset_ = quad_offset;
auto* quad =
render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
quad->SetNew(shared_quad_state, gfx::Rect(1, 1), gfx::Rect(1, 1),
SkColors::kTransparent, false);
}
float GetIdealContentsScaleKey() const override { return 1.f; }
gfx::Vector2d quad_offset_;
};
TEST_F(TileBasedLayerImplTest, AppendQuadsComputesQuadOffset) {
const gfx::Size layer_bounds(100, 100);
const gfx::Rect visible_layer_rect(10, 20, 50, 60);
auto layer = std::make_unique<QuadOffsetTestTileBasedLayerImpl>(
host_impl()->active_tree(), 1);
auto* raw_layer = layer.get();
host_impl()->active_tree()->AddLayer(std::move(layer));
raw_layer->SetBounds(layer_bounds);
raw_layer->draw_properties().visible_layer_rect = visible_layer_rect;
SetupRootProperties(host_impl()->active_tree()->root_layer());
auto render_pass = viz::CompositorRenderPass::Create();
AppendQuadsData data;
raw_layer->AppendQuads(AppendQuadsContext{DRAW_MODE_SOFTWARE, {}, false},
render_pass.get(), &data);
const gfx::Vector2d expected_quad_offset(-visible_layer_rect.x(),
-visible_layer_rect.y());
EXPECT_EQ(raw_layer->quad_offset(), expected_quad_offset);
ASSERT_EQ(render_pass->shared_quad_state_list.size(), 1u);
const viz::SharedQuadState* shared_quad_state =
render_pass->shared_quad_state_list.front();
gfx::Transform expected_transform =
raw_layer->draw_properties().target_space_transform;
expected_transform.Translate(-expected_quad_offset);
EXPECT_EQ(shared_quad_state->quad_to_target_transform, expected_transform);
gfx::Rect expected_quad_layer_rect = gfx::Rect(layer_bounds);
expected_quad_layer_rect.Offset(expected_quad_offset);
EXPECT_EQ(shared_quad_state->quad_layer_rect, expected_quad_layer_rect);
gfx::Rect expected_visible_quad_layer_rect = visible_layer_rect;
expected_visible_quad_layer_rect.Offset(expected_quad_offset);
EXPECT_EQ(shared_quad_state->visible_quad_layer_rect,
expected_visible_quad_layer_rect);
}
class QuadOffsetOrderTestTileBasedLayerImpl : public TestTileBasedLayerImpl {
public:
QuadOffsetOrderTestTileBasedLayerImpl(LayerTreeImpl* tree_impl, int id)
: TestTileBasedLayerImpl(tree_impl, id) {}
const viz::SharedQuadState* shared_quad_state_at_specialization() const {
return shared_quad_state_at_specialization_.get();
}
private:
void AppendQuadsSpecialization(const AppendQuadsContext& context,
viz::CompositorRenderPass* render_pass,
AppendQuadsData* append_quads_data,
viz::SharedQuadState* shared_quad_state,
const Occlusion& scaled_occlusion,
const gfx::Vector2d& quad_offset) override {
shared_quad_state_at_specialization_ =
std::make_unique<viz::SharedQuadState>(*shared_quad_state);
auto* quad =
render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
quad->SetNew(shared_quad_state, gfx::Rect(1, 1), gfx::Rect(1, 1),
SkColors::kTransparent, false);
}
float GetIdealContentsScaleKey() const override { return 1.f; }
std::unique_ptr<viz::SharedQuadState> shared_quad_state_at_specialization_;
};
TEST_F(
TileBasedLayerImplTest,
AppendQuadsUpdatesSharedQuadStateWithOffsetOnlyAfterCallingSpecialization) {
const gfx::Size layer_bounds(100, 100);
const gfx::Rect visible_layer_rect(10, 20, 50, 60);
auto layer = std::make_unique<QuadOffsetOrderTestTileBasedLayerImpl>(
host_impl()->active_tree(), 1);
auto* raw_layer = layer.get();
host_impl()->active_tree()->AddLayer(std::move(layer));
raw_layer->SetBounds(layer_bounds);
raw_layer->draw_properties().visible_layer_rect = visible_layer_rect;
SetupRootProperties(host_impl()->active_tree()->root_layer());
auto render_pass = viz::CompositorRenderPass::Create();
AppendQuadsData data;
raw_layer->AppendQuads(AppendQuadsContext{DRAW_MODE_SOFTWARE, {}, false},
render_pass.get(), &data);
const viz::SharedQuadState* sqs_at_specialization =
raw_layer->shared_quad_state_at_specialization();
ASSERT_TRUE(sqs_at_specialization);
EXPECT_EQ(sqs_at_specialization->quad_to_target_transform,
raw_layer->draw_properties().target_space_transform);
EXPECT_EQ(sqs_at_specialization->quad_layer_rect, gfx::Rect(layer_bounds));
EXPECT_EQ(sqs_at_specialization->visible_quad_layer_rect, visible_layer_rect);
ASSERT_EQ(render_pass->shared_quad_state_list.size(), 1u);
const viz::SharedQuadState* final_sqs =
render_pass->shared_quad_state_list.front();
const gfx::Vector2d expected_quad_offset(-visible_layer_rect.x(),
-visible_layer_rect.y());
gfx::Transform expected_transform =
raw_layer->draw_properties().target_space_transform;
expected_transform.Translate(-expected_quad_offset);
EXPECT_EQ(final_sqs->quad_to_target_transform, expected_transform);
gfx::Rect expected_quad_layer_rect = gfx::Rect(layer_bounds);
expected_quad_layer_rect.Offset(expected_quad_offset);
EXPECT_EQ(final_sqs->quad_layer_rect, expected_quad_layer_rect);
gfx::Rect expected_visible_quad_layer_rect = visible_layer_rect;
expected_visible_quad_layer_rect.Offset(expected_quad_offset);
EXPECT_EQ(final_sqs->visible_quad_layer_rect,
expected_visible_quad_layer_rect);
}
}
}