Index: cc/output/overlay_unittest.cc |
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc |
index 1820ad98ade27447069b5eea5099953f93f4cd51..684349caf788f64b3a224c06589343aa7c9707f6 100644 |
--- a/cc/output/overlay_unittest.cc |
+++ b/cc/output/overlay_unittest.cc |
@@ -9,6 +9,7 @@ |
#include "cc/output/output_surface_client.h" |
#include "cc/output/overlay_candidate_validator.h" |
#include "cc/output/overlay_processor.h" |
+#include "cc/output/overlay_strategy_sandwich.h" |
#include "cc/output/overlay_strategy_single_on_top.h" |
#include "cc/output/overlay_strategy_underlay.h" |
#include "cc/quads/render_pass.h" |
@@ -31,6 +32,7 @@ using testing::Mock; |
namespace cc { |
namespace { |
+const gfx::Size kDisplaySize(256, 256); |
const gfx::Rect kOverlayRect(0, 0, 128, 128); |
const gfx::Rect kOverlayTopLeftRect(0, 0, 64, 64); |
const gfx::Rect kOverlayBottomRightRect(64, 64, 64, 64); |
@@ -54,26 +56,42 @@ void MailboxReleased(unsigned sync_point, |
class SingleOverlayValidator : public OverlayCandidateValidator { |
public: |
- void CheckOverlaySupport(OverlayCandidateList* surfaces) override; |
+ void GetStrategies(OverlayProcessor::StrategyList* strategies) override { |
+ strategies->push_back(scoped_ptr<OverlayProcessor::Strategy>( |
+ new OverlayStrategyCommon(this, new OverlayStrategySingleOnTop))); |
+ strategies->push_back(scoped_ptr<OverlayProcessor::Strategy>( |
+ new OverlayStrategyCommon(this, new OverlayStrategyUnderlay))); |
+ } |
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override { |
+ ASSERT_EQ(2U, surfaces->size()); |
+ |
+ OverlayCandidate& candidate = surfaces->back(); |
+ if (candidate.display_rect.width() == 64) { |
+ EXPECT_EQ(kOverlayBottomRightRect, candidate.display_rect); |
+ } else { |
+ EXPECT_NEAR(kOverlayRect.x(), candidate.display_rect.x(), 0.01f); |
+ EXPECT_NEAR(kOverlayRect.y(), candidate.display_rect.y(), 0.01f); |
+ EXPECT_NEAR(kOverlayRect.width(), candidate.display_rect.width(), 0.01f); |
+ EXPECT_NEAR(kOverlayRect.height(), candidate.display_rect.height(), |
+ 0.01f); |
+ } |
+ EXPECT_EQ(BoundingRect(kUVTopLeft, kUVBottomRight).ToString(), |
+ candidate.uv_rect.ToString()); |
+ candidate.overlay_handled = true; |
+ } |
}; |
-void SingleOverlayValidator::CheckOverlaySupport( |
- OverlayCandidateList* surfaces) { |
- ASSERT_EQ(2U, surfaces->size()); |
- |
- OverlayCandidate& candidate = surfaces->back(); |
- if (candidate.display_rect.width() == 64) { |
- EXPECT_EQ(kOverlayBottomRightRect, candidate.display_rect); |
- } else { |
- EXPECT_NEAR(kOverlayRect.x(), candidate.display_rect.x(), 0.01f); |
- EXPECT_NEAR(kOverlayRect.y(), candidate.display_rect.y(), 0.01f); |
- EXPECT_NEAR(kOverlayRect.width(), candidate.display_rect.width(), 0.01f); |
- EXPECT_NEAR(kOverlayRect.height(), candidate.display_rect.height(), 0.01f); |
+class SandwichOverlayValidator : public OverlayCandidateValidator { |
+ public: |
+ void GetStrategies(OverlayProcessor::StrategyList* strategies) override { |
+ strategies->push_back(scoped_ptr<OverlayProcessor::Strategy>( |
+ new OverlayStrategyCommon(this, new OverlayStrategySandwich))); |
} |
- EXPECT_EQ(BoundingRect(kUVTopLeft, kUVBottomRight).ToString(), |
- candidate.uv_rect.ToString()); |
- candidate.overlay_handled = true; |
-} |
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override { |
+ for (OverlayCandidate& candidate : *surfaces) |
+ candidate.overlay_handled = true; |
+ } |
+}; |
template <typename OverlayStrategyType> |
class SingleOverlayProcessor : public OverlayProcessor { |
@@ -85,11 +103,11 @@ class SingleOverlayProcessor : public OverlayProcessor { |
// Virtual to allow testing different strategies. |
void Initialize() override { |
- OverlayCandidateValidator* candidates = |
+ OverlayCandidateValidator* validator = |
surface_->GetOverlayCandidateValidator(); |
- ASSERT_TRUE(candidates != NULL); |
- strategies_.push_back( |
- scoped_ptr<Strategy>(new OverlayStrategyType(candidates))); |
+ ASSERT_TRUE(validator != NULL); |
+ strategies_.push_back(scoped_ptr<Strategy>( |
+ new OverlayStrategyCommon(validator, new OverlayStrategyType))); |
} |
}; |
@@ -110,7 +128,14 @@ size_t DefaultOverlayProcessor::GetStrategyCount() { |
class OverlayOutputSurface : public OutputSurface { |
public: |
explicit OverlayOutputSurface(scoped_refptr<ContextProvider> context_provider) |
- : OutputSurface(context_provider) {} |
+ : OutputSurface(context_provider) { |
+ surface_size_ = kDisplaySize; |
+ device_scale_factor_ = 1; |
+ } |
+ |
+ void SetScaleFactor(float scale_factor) { |
+ device_scale_factor_ = scale_factor; |
+ } |
// OutputSurface implementation |
void SwapBuffers(CompositorFrame* frame) override; |
@@ -118,6 +143,9 @@ class OverlayOutputSurface : public OutputSurface { |
void InitWithSingleOverlayValidator() { |
overlay_candidate_validator_.reset(new SingleOverlayValidator); |
} |
+ void InitWithSandwichOverlayValidator() { |
+ overlay_candidate_validator_.reset(new SandwichOverlayValidator); |
+ } |
OverlayCandidateValidator* GetOverlayCandidateValidator() const override { |
return overlay_candidate_validator_.get(); |
@@ -342,6 +370,178 @@ class OverlayTest : public testing::Test { |
typedef OverlayTest<OverlayStrategySingleOnTop> SingleOverlayOnTopTest; |
typedef OverlayTest<OverlayStrategyUnderlay> UnderlayTest; |
+class SandwichTest : public testing::Test { |
+ protected: |
+ void SetUp() override { |
+ provider_ = TestContextProvider::Create(); |
+ output_surface_.reset(new OverlayOutputSurface(provider_)); |
+ EXPECT_TRUE(output_surface_->BindToClient(&client_)); |
+ output_surface_->InitWithSandwichOverlayValidator(); |
+ EXPECT_TRUE(output_surface_->GetOverlayCandidateValidator() != NULL); |
+ |
+ shared_bitmap_manager_.reset(new TestSharedBitmapManager()); |
+ resource_provider_ = FakeResourceProvider::Create( |
+ output_surface_.get(), shared_bitmap_manager_.get()); |
+ |
+ overlay_processor_.reset(new OverlayProcessor(output_surface_.get())); |
+ overlay_processor_->Initialize(); |
+ } |
+ |
+ scoped_refptr<TestContextProvider> provider_; |
+ scoped_ptr<OverlayOutputSurface> output_surface_; |
+ FakeOutputSurfaceClient client_; |
+ scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; |
+ scoped_ptr<ResourceProvider> resource_provider_; |
+ scoped_ptr<OverlayProcessor> overlay_processor_; |
+}; |
+ |
+TEST_F(SandwichTest, SuccessfulSingleOverlay) { |
+ scoped_ptr<RenderPass> pass = CreateRenderPass(); |
+ TextureDrawQuad* original_quad = CreateFullscreenCandidateQuad( |
+ resource_provider_.get(), pass->shared_quad_state_list.back(), |
+ pass.get()); |
+ unsigned original_resource_id = original_quad->resource_id(); |
+ |
+ // Add something behind it. |
+ CreateFullscreenOpaqueQuad(resource_provider_.get(), |
+ pass->shared_quad_state_list.back(), pass.get()); |
+ CreateFullscreenOpaqueQuad(resource_provider_.get(), |
+ pass->shared_quad_state_list.back(), pass.get()); |
+ |
+ RenderPassList pass_list; |
+ pass_list.push_back(pass.Pass()); |
+ |
+ // Check for potential candidates. |
+ OverlayCandidateList candidate_list; |
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); |
+ |
+ ASSERT_EQ(1U, pass_list.size()); |
+ ASSERT_EQ(2U, candidate_list.size()); |
+ |
+ RenderPass* main_pass = pass_list.back(); |
+ // Check that the quad is gone. |
+ EXPECT_EQ(2U, main_pass->quad_list.size()); |
+ const QuadList& quad_list = main_pass->quad_list; |
+ for (QuadList::ConstBackToFrontIterator it = quad_list.BackToFrontBegin(); |
+ it != quad_list.BackToFrontEnd(); ++it) { |
+ EXPECT_NE(DrawQuad::TEXTURE_CONTENT, it->material); |
+ } |
+ |
+ // Check that the right resource id got extracted. |
+ EXPECT_EQ(original_resource_id, candidate_list.back().resource_id); |
+} |
+ |
+TEST_F(SandwichTest, SuccessfulSandwichOverlay) { |
+ scoped_ptr<RenderPass> pass = CreateRenderPass(); |
+ |
+ CreateOpaqueQuadAt(resource_provider_.get(), |
+ pass->shared_quad_state_list.back(), pass.get(), |
+ gfx::Rect(16, 16, 32, 32)); |
+ unsigned candidate_id = |
+ CreateCandidateQuadAt(resource_provider_.get(), |
+ pass->shared_quad_state_list.back(), pass.get(), |
+ gfx::Rect(32, 32, 32, 32)) |
+ ->resource_id(); |
+ CreateOpaqueQuadAt(resource_provider_.get(), |
+ pass->shared_quad_state_list.back(), pass.get(), |
+ gfx::Rect(kDisplaySize)); |
+ |
+ RenderPassList pass_list; |
+ pass_list.push_back(pass.Pass()); |
+ |
+ // Check for potential candidates. |
+ OverlayCandidateList candidate_list; |
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); |
+ |
+ ASSERT_EQ(1U, pass_list.size()); |
+ ASSERT_EQ(3U, candidate_list.size()); |
+ |
+ RenderPass* main_pass = pass_list.back(); |
+ // Check that the quad is gone. |
+ EXPECT_EQ(3U, main_pass->quad_list.size()); |
+ const QuadList& quad_list = main_pass->quad_list; |
+ for (QuadList::ConstBackToFrontIterator it = quad_list.BackToFrontBegin(); |
+ it != quad_list.BackToFrontEnd(); ++it) { |
+ EXPECT_NE(DrawQuad::TEXTURE_CONTENT, it->material); |
+ } |
+ |
+ EXPECT_FALSE(candidate_list[0].use_output_surface_for_resource); |
+ EXPECT_EQ(candidate_id, candidate_list[1].resource_id); |
+ EXPECT_EQ(gfx::Rect(32, 32, 32, 32), candidate_list[1].display_rect); |
+ EXPECT_TRUE(candidate_list[2].use_output_surface_for_resource); |
+ EXPECT_EQ(gfx::Rect(32, 32, 16, 16), candidate_list[2].display_rect); |
+ EXPECT_EQ(gfx::RectF(32. / 256, 32. / 256, 16. / 256, 16. / 256), |
+ candidate_list[2].uv_rect); |
+} |
+ |
+TEST_F(SandwichTest, GrowTopOverlayForToAlignWithDIP) { |
+ output_surface_->SetScaleFactor(2); |
+ scoped_ptr<RenderPass> pass = CreateRenderPass(); |
+ |
+ // The opaque quad on top is not DIP aligned, so it should be enlarged to |
+ // include the surrounding DIP. |
+ CreateOpaqueQuadAt(resource_provider_.get(), |
+ pass->shared_quad_state_list.back(), pass.get(), |
+ gfx::Rect(16, 16, 33, 33)); |
+ unsigned candidate_id = |
+ CreateCandidateQuadAt(resource_provider_.get(), |
+ pass->shared_quad_state_list.back(), pass.get(), |
+ gfx::Rect(32, 32, 32, 32)) |
+ ->resource_id(); |
+ CreateOpaqueQuadAt(resource_provider_.get(), |
+ pass->shared_quad_state_list.back(), pass.get(), |
+ gfx::Rect(kDisplaySize)); |
+ |
+ RenderPassList pass_list; |
+ pass_list.push_back(pass.Pass()); |
+ |
+ // Check for potential candidates. |
+ OverlayCandidateList candidate_list; |
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); |
+ ASSERT_EQ(1U, pass_list.size()); |
+ ASSERT_EQ(3U, candidate_list.size()); |
+ |
+ // Check that the quad is gone. |
+ RenderPass* main_pass = pass_list.back(); |
+ EXPECT_EQ(3U, main_pass->quad_list.size()); |
+ const QuadList& quad_list = main_pass->quad_list; |
+ for (QuadList::ConstBackToFrontIterator it = quad_list.BackToFrontBegin(); |
+ it != quad_list.BackToFrontEnd(); ++it) { |
+ EXPECT_NE(DrawQuad::TEXTURE_CONTENT, it->material); |
+ } |
+ |
+ EXPECT_FALSE(candidate_list[0].use_output_surface_for_resource); |
+ EXPECT_EQ(candidate_id, candidate_list[1].resource_id); |
+ EXPECT_EQ(gfx::Rect(32, 32, 32, 32), candidate_list[1].display_rect); |
+ EXPECT_TRUE(candidate_list[2].use_output_surface_for_resource); |
+ EXPECT_EQ(gfx::Rect(32, 32, 18, 18), candidate_list[2].display_rect); |
+ EXPECT_EQ(gfx::RectF(32. / 256, 32. / 256, 18. / 256, 18. / 256), |
+ candidate_list[2].uv_rect); |
+} |
+ |
+TEST_F(SandwichTest, MisalignedOverlay) { |
+ output_surface_->SetScaleFactor(2); |
+ scoped_ptr<RenderPass> pass = CreateRenderPass(); |
+ |
+ // We can't create an overlay for a candidate that is not DIP aligned. |
+ CreateCandidateQuadAt(resource_provider_.get(), |
+ pass->shared_quad_state_list.back(), pass.get(), |
+ gfx::Rect(32, 32, 33, 33)) |
+ ->resource_id(); |
+ CreateOpaqueQuadAt(resource_provider_.get(), |
+ pass->shared_quad_state_list.back(), pass.get(), |
+ gfx::Rect(kDisplaySize)); |
+ |
+ RenderPassList pass_list; |
+ pass_list.push_back(pass.Pass()); |
+ |
+ OverlayCandidateList candidate_list; |
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); |
+ |
+ ASSERT_EQ(1U, pass_list.size()); |
+ ASSERT_EQ(0U, candidate_list.size()); |
+} |
+ |
TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) { |
scoped_ptr<RenderPass> pass = CreateRenderPass(); |
TextureDrawQuad* original_quad = |