| // Copyright 2012 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 "cc/test/layer_test_common.h" |
| |
| #include "cc/base/math_util.h" |
| #include "cc/base/region.h" |
| #include "cc/layers/append_quads_data.h" |
| #include "cc/quads/draw_quad.h" |
| #include "cc/quads/render_pass.h" |
| #include "cc/test/fake_output_surface.h" |
| #include "cc/test/mock_occlusion_tracker.h" |
| #include "cc/trees/layer_tree_host_common.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gfx/geometry/point_conversions.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/rect_conversions.h" |
| #include "ui/gfx/geometry/size_conversions.h" |
| |
| namespace cc { |
| |
| // Align with expected and actual output. |
| const char* LayerTestCommon::quad_string = " Quad: "; |
| |
| static bool CanRectFBeSafelyRoundedToRect(const gfx::RectF& r) { |
| // Ensure that range of float values is not beyond integer range. |
| if (!r.IsExpressibleAsRect()) |
| return false; |
| |
| // Ensure that the values are actually integers. |
| if (gfx::ToFlooredPoint(r.origin()) == r.origin() && |
| gfx::ToFlooredSize(r.size()) == r.size()) |
| return true; |
| |
| return false; |
| } |
| |
| void LayerTestCommon::VerifyQuadsExactlyCoverRect(const QuadList& quads, |
| const gfx::Rect& rect) { |
| Region remaining = rect; |
| |
| for (auto iter = quads.cbegin(); iter != quads.cend(); ++iter) { |
| gfx::RectF quad_rectf = |
| MathUtil::MapClippedRect(iter->quadTransform(), gfx::RectF(iter->rect)); |
| |
| // Before testing for exact coverage in the integer world, assert that |
| // rounding will not round the rect incorrectly. |
| ASSERT_TRUE(CanRectFBeSafelyRoundedToRect(quad_rectf)); |
| |
| gfx::Rect quad_rect = gfx::ToEnclosingRect(quad_rectf); |
| |
| EXPECT_TRUE(rect.Contains(quad_rect)) << quad_string << iter.index() |
| << " rect: " << rect.ToString() |
| << " quad: " << quad_rect.ToString(); |
| EXPECT_TRUE(remaining.Contains(quad_rect)) |
| << quad_string << iter.index() << " remaining: " << remaining.ToString() |
| << " quad: " << quad_rect.ToString(); |
| remaining.Subtract(quad_rect); |
| } |
| |
| EXPECT_TRUE(remaining.IsEmpty()); |
| } |
| |
| // static |
| void LayerTestCommon::VerifyQuadsAreOccluded(const QuadList& quads, |
| const gfx::Rect& occluded, |
| size_t* partially_occluded_count) { |
| // No quad should exist if it's fully occluded. |
| for (const auto& quad : quads) { |
| gfx::Rect target_visible_rect = MathUtil::MapEnclosingClippedRect( |
| quad->quadTransform(), quad->visible_rect); |
| EXPECT_FALSE(occluded.Contains(target_visible_rect)); |
| } |
| |
| // Quads that are fully occluded on one axis only should be shrunken. |
| for (const auto& quad : quads) { |
| DCHECK(quad->quadTransform().IsIdentityOrIntegerTranslation()); |
| gfx::Rect target_rect = |
| MathUtil::MapEnclosingClippedRect(quad->quadTransform(), quad->rect); |
| gfx::Rect target_visible_rect = MathUtil::MapEnclosingClippedRect( |
| quad->quadTransform(), quad->visible_rect); |
| |
| bool fully_occluded_horizontal = target_rect.x() >= occluded.x() && |
| target_rect.right() <= occluded.right(); |
| bool fully_occluded_vertical = target_rect.y() >= occluded.y() && |
| target_rect.bottom() <= occluded.bottom(); |
| bool should_be_occluded = |
| target_rect.Intersects(occluded) && |
| (fully_occluded_vertical || fully_occluded_horizontal); |
| if (!should_be_occluded) { |
| EXPECT_EQ(quad->rect.ToString(), quad->visible_rect.ToString()); |
| } else { |
| EXPECT_NE(quad->rect.ToString(), quad->visible_rect.ToString()); |
| EXPECT_TRUE(quad->rect.Contains(quad->visible_rect)); |
| ++(*partially_occluded_count); |
| } |
| } |
| } |
| |
| LayerTestCommon::LayerImplTest::LayerImplTest() |
| : client_(FakeLayerTreeHostClient::DIRECT_3D), |
| host_(FakeLayerTreeHost::Create(&client_)), |
| root_layer_impl_(LayerImpl::Create(host_->host_impl()->active_tree(), 1)), |
| render_pass_(RenderPass::Create()) { |
| root_layer_impl_->SetHasRenderSurface(true); |
| scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d(); |
| host_->host_impl()->InitializeRenderer(FakeOutputSurface::Create3d()); |
| } |
| |
| LayerTestCommon::LayerImplTest::~LayerImplTest() {} |
| |
| void LayerTestCommon::LayerImplTest::CalcDrawProps( |
| const gfx::Size& viewport_size) { |
| LayerImplList layer_list; |
| LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( |
| root_layer_impl_.get(), viewport_size, &layer_list); |
| LayerTreeHostCommon::CalculateDrawProperties(&inputs); |
| } |
| |
| void LayerTestCommon::LayerImplTest::AppendQuadsWithOcclusion( |
| LayerImpl* layer_impl, |
| const gfx::Rect& occluded) { |
| AppendQuadsData data; |
| |
| render_pass_->quad_list.clear(); |
| render_pass_->shared_quad_state_list.clear(); |
| |
| Occlusion occlusion(layer_impl->draw_transform(), |
| SimpleEnclosedRegion(occluded), |
| SimpleEnclosedRegion()); |
| |
| layer_impl->WillDraw(DRAW_MODE_HARDWARE, resource_provider()); |
| layer_impl->AppendQuads(render_pass_.get(), occlusion, &data); |
| layer_impl->DidDraw(resource_provider()); |
| } |
| |
| void LayerTestCommon::LayerImplTest::AppendQuadsForPassWithOcclusion( |
| LayerImpl* layer_impl, |
| RenderPass* given_render_pass, |
| const gfx::Rect& occluded) { |
| AppendQuadsData data; |
| |
| given_render_pass->quad_list.clear(); |
| given_render_pass->shared_quad_state_list.clear(); |
| |
| Occlusion occlusion(layer_impl->draw_transform(), |
| SimpleEnclosedRegion(occluded), |
| SimpleEnclosedRegion()); |
| |
| layer_impl->WillDraw(DRAW_MODE_HARDWARE, resource_provider()); |
| layer_impl->AppendQuads(given_render_pass, occlusion, &data); |
| layer_impl->DidDraw(resource_provider()); |
| } |
| |
| void LayerTestCommon::LayerImplTest::AppendSurfaceQuadsWithOcclusion( |
| RenderSurfaceImpl* surface_impl, |
| const gfx::Rect& occluded) { |
| AppendQuadsData data; |
| |
| render_pass_->quad_list.clear(); |
| render_pass_->shared_quad_state_list.clear(); |
| occlusion_tracker_.set_occluded_target_rect_for_contributing_surface( |
| occluded); |
| bool for_replica = false; |
| RenderPassId id(1, 1); |
| surface_impl->AppendQuads( |
| render_pass_.get(), occlusion_tracker_, &data, for_replica, id); |
| } |
| |
| } // namespace cc |