| // Copyright 2014 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/base/scoped_ptr_vector.h" |
| #include "cc/output/gl_renderer.h" |
| #include "cc/output/output_surface.h" |
| #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_single_on_top.h" |
| #include "cc/quads/checkerboard_draw_quad.h" |
| #include "cc/quads/render_pass.h" |
| #include "cc/quads/texture_draw_quad.h" |
| #include "cc/resources/resource_provider.h" |
| #include "cc/resources/texture_mailbox.h" |
| #include "cc/test/fake_output_surface_client.h" |
| #include "cc/test/geometry_test_utils.h" |
| #include "cc/test/test_context_provider.h" |
| #include "cc/test/test_shared_bitmap_manager.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using testing::_; |
| using testing::Mock; |
| |
| namespace cc { |
| namespace { |
| |
| const gfx::Rect kOverlayRect(0, 0, 128, 128); |
| const gfx::Rect kOverlayTopLeftRect(0, 0, 64, 64); |
| const gfx::Rect kOverlayBottomRightRect(64, 64, 64, 64); |
| const gfx::PointF kUVTopLeft(0.1f, 0.2f); |
| const gfx::PointF kUVBottomRight(1.0f, 1.0f); |
| |
| void MailboxReleased(unsigned sync_point, |
| bool lost_resource, |
| BlockingTaskRunner* main_thread_task_runner) { |
| } |
| |
| class SingleOverlayValidator : public OverlayCandidateValidator { |
| public: |
| void CheckOverlaySupport(OverlayCandidateList* surfaces) override; |
| }; |
| |
| 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_EQ(kOverlayRect, candidate.display_rect); |
| EXPECT_EQ(BoundingRect(kUVTopLeft, kUVBottomRight).ToString(), |
| candidate.uv_rect.ToString()); |
| candidate.overlay_handled = true; |
| } |
| |
| class SingleOverlayProcessor : public OverlayProcessor { |
| public: |
| SingleOverlayProcessor(OutputSurface* surface, |
| ResourceProvider* resource_provider); |
| // Virtual to allow testing different strategies. |
| void Initialize() override; |
| }; |
| |
| SingleOverlayProcessor::SingleOverlayProcessor( |
| OutputSurface* surface, |
| ResourceProvider* resource_provider) |
| : OverlayProcessor(surface, resource_provider) { |
| EXPECT_EQ(surface, surface_); |
| EXPECT_EQ(resource_provider, resource_provider_); |
| } |
| |
| void SingleOverlayProcessor::Initialize() { |
| OverlayCandidateValidator* candidates = |
| surface_->overlay_candidate_validator(); |
| ASSERT_TRUE(candidates != NULL); |
| strategies_.push_back(scoped_ptr<Strategy>( |
| new OverlayStrategySingleOnTop(candidates, resource_provider_))); |
| } |
| |
| class DefaultOverlayProcessor : public OverlayProcessor { |
| public: |
| DefaultOverlayProcessor(OutputSurface* surface, |
| ResourceProvider* resource_provider); |
| size_t GetStrategyCount(); |
| }; |
| |
| DefaultOverlayProcessor::DefaultOverlayProcessor( |
| OutputSurface* surface, |
| ResourceProvider* resource_provider) |
| : OverlayProcessor(surface, resource_provider) {} |
| |
| size_t DefaultOverlayProcessor::GetStrategyCount() { |
| return strategies_.size(); |
| } |
| |
| class OverlayOutputSurface : public OutputSurface { |
| public: |
| explicit OverlayOutputSurface(scoped_refptr<ContextProvider> context_provider) |
| : OutputSurface(context_provider) {} |
| |
| // OutputSurface implementation |
| void SwapBuffers(CompositorFrame* frame) override; |
| |
| void InitWithSingleOverlayValidator() { |
| overlay_candidate_validator_.reset(new SingleOverlayValidator); |
| } |
| }; |
| |
| void OverlayOutputSurface::SwapBuffers(CompositorFrame* frame) { |
| client_->DidSwapBuffers(); |
| client_->DidSwapBuffersComplete(); |
| } |
| |
| scoped_ptr<RenderPass> CreateRenderPass() { |
| RenderPassId id(1, 0); |
| gfx::Rect output_rect(0, 0, 256, 256); |
| bool has_transparent_background = true; |
| |
| scoped_ptr<RenderPass> pass = RenderPass::Create(); |
| pass->SetAll(id, |
| output_rect, |
| output_rect, |
| gfx::Transform(), |
| has_transparent_background); |
| |
| SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState(); |
| shared_state->opacity = 1.f; |
| return pass.Pass(); |
| } |
| |
| ResourceProvider::ResourceId CreateResource( |
| ResourceProvider* resource_provider) { |
| unsigned sync_point = 0; |
| TextureMailbox mailbox = |
| TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point); |
| mailbox.set_allow_overlay(true); |
| scoped_ptr<SingleReleaseCallbackImpl> release_callback = |
| SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased)); |
| |
| return resource_provider->CreateResourceFromTextureMailbox( |
| mailbox, release_callback.Pass()); |
| } |
| |
| TextureDrawQuad* CreateCandidateQuadAt(ResourceProvider* resource_provider, |
| const SharedQuadState* shared_quad_state, |
| RenderPass* render_pass, |
| const gfx::Rect& rect) { |
| ResourceProvider::ResourceId resource_id = CreateResource(resource_provider); |
| bool premultiplied_alpha = false; |
| bool flipped = false; |
| float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f}; |
| |
| TextureDrawQuad* overlay_quad = |
| render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); |
| overlay_quad->SetNew(shared_quad_state, |
| rect, |
| rect, |
| rect, |
| resource_id, |
| premultiplied_alpha, |
| kUVTopLeft, |
| kUVBottomRight, |
| SK_ColorTRANSPARENT, |
| vertex_opacity, |
| flipped); |
| |
| return overlay_quad; |
| } |
| |
| TextureDrawQuad* CreateFullscreenCandidateQuad( |
| ResourceProvider* resource_provider, |
| const SharedQuadState* shared_quad_state, |
| RenderPass* render_pass) { |
| return CreateCandidateQuadAt( |
| resource_provider, shared_quad_state, render_pass, kOverlayRect); |
| } |
| |
| void CreateCheckeredQuadAt(ResourceProvider* resource_provider, |
| const SharedQuadState* shared_quad_state, |
| RenderPass* render_pass, |
| const gfx::Rect& rect) { |
| CheckerboardDrawQuad* checkerboard_quad = |
| render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>(); |
| checkerboard_quad->SetNew(shared_quad_state, rect, rect, SkColor()); |
| } |
| |
| void CreateFullscreenCheckeredQuad(ResourceProvider* resource_provider, |
| const SharedQuadState* shared_quad_state, |
| RenderPass* render_pass) { |
| CreateCheckeredQuadAt( |
| resource_provider, shared_quad_state, render_pass, kOverlayRect); |
| } |
| |
| static void CompareRenderPassLists(const RenderPassList& expected_list, |
| const RenderPassList& actual_list) { |
| EXPECT_EQ(expected_list.size(), actual_list.size()); |
| for (size_t i = 0; i < actual_list.size(); ++i) { |
| RenderPass* expected = expected_list[i]; |
| RenderPass* actual = actual_list[i]; |
| |
| EXPECT_EQ(expected->id, actual->id); |
| EXPECT_RECT_EQ(expected->output_rect, actual->output_rect); |
| EXPECT_EQ(expected->transform_to_root_target, |
| actual->transform_to_root_target); |
| EXPECT_RECT_EQ(expected->damage_rect, actual->damage_rect); |
| EXPECT_EQ(expected->has_transparent_background, |
| actual->has_transparent_background); |
| |
| EXPECT_EQ(expected->shared_quad_state_list.size(), |
| actual->shared_quad_state_list.size()); |
| EXPECT_EQ(expected->quad_list.size(), actual->quad_list.size()); |
| |
| for (auto exp_iter = expected->quad_list.cbegin(), |
| act_iter = actual->quad_list.cbegin(); |
| exp_iter != expected->quad_list.cend(); |
| ++exp_iter, ++act_iter) { |
| EXPECT_EQ(exp_iter->rect.ToString(), act_iter->rect.ToString()); |
| EXPECT_EQ(exp_iter->shared_quad_state->content_bounds.ToString(), |
| act_iter->shared_quad_state->content_bounds.ToString()); |
| } |
| } |
| } |
| |
| TEST(OverlayTest, NoOverlaysByDefault) { |
| scoped_refptr<TestContextProvider> provider = TestContextProvider::Create(); |
| OverlayOutputSurface output_surface(provider); |
| EXPECT_EQ(NULL, output_surface.overlay_candidate_validator()); |
| |
| output_surface.InitWithSingleOverlayValidator(); |
| EXPECT_TRUE(output_surface.overlay_candidate_validator() != NULL); |
| } |
| |
| TEST(OverlayTest, OverlaysProcessorHasStrategy) { |
| scoped_refptr<TestContextProvider> provider = TestContextProvider::Create(); |
| OverlayOutputSurface output_surface(provider); |
| FakeOutputSurfaceClient client; |
| EXPECT_TRUE(output_surface.BindToClient(&client)); |
| output_surface.InitWithSingleOverlayValidator(); |
| EXPECT_TRUE(output_surface.overlay_candidate_validator() != NULL); |
| |
| scoped_ptr<SharedBitmapManager> shared_bitmap_manager( |
| new TestSharedBitmapManager()); |
| scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( |
| &output_surface, shared_bitmap_manager.get(), NULL, NULL, 0, false, 1)); |
| |
| scoped_ptr<DefaultOverlayProcessor> overlay_processor( |
| new DefaultOverlayProcessor(&output_surface, resource_provider.get())); |
| overlay_processor->Initialize(); |
| EXPECT_GE(1U, overlay_processor->GetStrategyCount()); |
| } |
| |
| class SingleOverlayOnTopTest : public testing::Test { |
| protected: |
| virtual void SetUp() { |
| provider_ = TestContextProvider::Create(); |
| output_surface_.reset(new OverlayOutputSurface(provider_)); |
| EXPECT_TRUE(output_surface_->BindToClient(&client_)); |
| output_surface_->InitWithSingleOverlayValidator(); |
| EXPECT_TRUE(output_surface_->overlay_candidate_validator() != NULL); |
| |
| shared_bitmap_manager_.reset(new TestSharedBitmapManager()); |
| resource_provider_ = ResourceProvider::Create(output_surface_.get(), |
| shared_bitmap_manager_.get(), |
| NULL, |
| NULL, |
| 0, |
| false, |
| 1); |
| |
| overlay_processor_.reset(new SingleOverlayProcessor( |
| output_surface_.get(), resource_provider_.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<SingleOverlayProcessor> overlay_processor_; |
| }; |
| |
| TEST_F(SingleOverlayOnTopTest, SuccessfullOverlay) { |
| 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. |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| CreateFullscreenCheckeredQuad(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(SingleOverlayOnTopTest, NoCandidates) { |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| |
| RenderPassList pass_list; |
| pass_list.push_back(pass.Pass()); |
| |
| RenderPassList original_pass_list; |
| RenderPass::CopyAll(pass_list, &original_pass_list); |
| |
| OverlayCandidateList candidate_list; |
| overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); |
| EXPECT_EQ(0U, candidate_list.size()); |
| // There should be nothing new here. |
| CompareRenderPassLists(pass_list, original_pass_list); |
| } |
| |
| TEST_F(SingleOverlayOnTopTest, OccludedCandidates) { |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| |
| CreateFullscreenCandidateQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| |
| RenderPassList pass_list; |
| pass_list.push_back(pass.Pass()); |
| |
| RenderPassList original_pass_list; |
| RenderPass::CopyAll(pass_list, &original_pass_list); |
| |
| OverlayCandidateList candidate_list; |
| overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); |
| EXPECT_EQ(0U, candidate_list.size()); |
| // There should be nothing new here. |
| CompareRenderPassLists(pass_list, original_pass_list); |
| } |
| |
| // Test with multiple render passes. |
| TEST_F(SingleOverlayOnTopTest, MultipleRenderPasses) { |
| RenderPassList pass_list; |
| pass_list.push_back(CreateRenderPass()); |
| |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| CreateFullscreenCandidateQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| |
| // Add something behind it. |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| |
| pass_list.push_back(pass.Pass()); |
| |
| RenderPassList original_pass_list; |
| RenderPass::CopyAll(pass_list, &original_pass_list); |
| |
| // Check for potential candidates. |
| OverlayCandidateList candidate_list; |
| overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); |
| EXPECT_EQ(2U, candidate_list.size()); |
| |
| // This should be the same. |
| ASSERT_EQ(2U, pass_list.size()); |
| } |
| |
| TEST_F(SingleOverlayOnTopTest, RejectPremultipliedAlpha) { |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| TextureDrawQuad* quad = |
| CreateFullscreenCandidateQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| quad->premultiplied_alpha = true; |
| |
| RenderPassList pass_list; |
| pass_list.push_back(pass.Pass()); |
| OverlayCandidateList candidate_list; |
| overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); |
| EXPECT_EQ(1U, pass_list.size()); |
| EXPECT_EQ(0U, candidate_list.size()); |
| } |
| |
| TEST_F(SingleOverlayOnTopTest, RejectBlending) { |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| TextureDrawQuad* quad = |
| CreateFullscreenCandidateQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| quad->needs_blending = true; |
| |
| 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()); |
| EXPECT_EQ(0U, candidate_list.size()); |
| } |
| |
| TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) { |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| TextureDrawQuad* quad = |
| CreateFullscreenCandidateQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| quad->background_color = SK_ColorBLACK; |
| |
| 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()); |
| EXPECT_EQ(0U, candidate_list.size()); |
| } |
| |
| TEST_F(SingleOverlayOnTopTest, RejectBlendMode) { |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| CreateFullscreenCandidateQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| pass->shared_quad_state_list.back()->blend_mode = SkXfermode::kScreen_Mode; |
| |
| 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()); |
| EXPECT_EQ(0U, candidate_list.size()); |
| } |
| |
| TEST_F(SingleOverlayOnTopTest, RejectOpacity) { |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| CreateFullscreenCandidateQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| pass->shared_quad_state_list.back()->opacity = 0.5f; |
| |
| 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()); |
| EXPECT_EQ(0U, candidate_list.size()); |
| } |
| |
| TEST_F(SingleOverlayOnTopTest, RejectTransform) { |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| CreateFullscreenCandidateQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| pass->shared_quad_state_list.back()->content_to_target_transform.Scale(2.f, |
| 2.f); |
| |
| 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()); |
| EXPECT_EQ(0U, candidate_list.size()); |
| } |
| |
| TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) { |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| CreateCheckeredQuadAt(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get(), |
| kOverlayTopLeftRect); |
| CreateCandidateQuadAt(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get(), |
| kOverlayBottomRightRect); |
| |
| RenderPassList pass_list; |
| pass_list.push_back(pass.Pass()); |
| |
| RenderPassList original_pass_list; |
| RenderPass::CopyAll(pass_list, &original_pass_list); |
| |
| OverlayCandidateList candidate_list; |
| overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list); |
| EXPECT_EQ(1U, pass_list.size()); |
| EXPECT_EQ(2U, candidate_list.size()); |
| } |
| |
| class OverlayInfoRendererGL : public GLRenderer { |
| public: |
| OverlayInfoRendererGL(RendererClient* client, |
| const RendererSettings* settings, |
| OutputSurface* output_surface, |
| ResourceProvider* resource_provider) |
| : GLRenderer(client, |
| settings, |
| output_surface, |
| resource_provider, |
| NULL, |
| 0), |
| expect_overlays_(false) {} |
| |
| MOCK_METHOD2(DoDrawQuad, void(DrawingFrame* frame, const DrawQuad* quad)); |
| |
| using GLRenderer::BeginDrawingFrame; |
| |
| void FinishDrawingFrame(DrawingFrame* frame) override { |
| GLRenderer::FinishDrawingFrame(frame); |
| |
| if (!expect_overlays_) { |
| EXPECT_EQ(0U, frame->overlay_list.size()); |
| return; |
| } |
| |
| ASSERT_EQ(2U, frame->overlay_list.size()); |
| EXPECT_NE(0U, frame->overlay_list.back().resource_id); |
| } |
| |
| void set_expect_overlays(bool expect_overlays) { |
| expect_overlays_ = expect_overlays; |
| } |
| |
| private: |
| bool expect_overlays_; |
| }; |
| |
| class FakeRendererClient : public RendererClient { |
| public: |
| // RendererClient methods. |
| void SetFullRootLayerDamage() override {} |
| }; |
| |
| class MockOverlayScheduler { |
| public: |
| MOCK_METHOD5(Schedule, |
| void(int plane_z_order, |
| gfx::OverlayTransform plane_transform, |
| unsigned overlay_texture_id, |
| const gfx::Rect& display_bounds, |
| const gfx::RectF& uv_rect)); |
| }; |
| |
| class GLRendererWithOverlaysTest : public testing::Test { |
| protected: |
| GLRendererWithOverlaysTest() { |
| provider_ = TestContextProvider::Create(); |
| output_surface_.reset(new OverlayOutputSurface(provider_)); |
| CHECK(output_surface_->BindToClient(&output_surface_client_)); |
| resource_provider_ = ResourceProvider::Create( |
| output_surface_.get(), NULL, NULL, NULL, 0, false, 1); |
| |
| provider_->support()->SetScheduleOverlayPlaneCallback(base::Bind( |
| &MockOverlayScheduler::Schedule, base::Unretained(&scheduler_))); |
| } |
| |
| void Init(bool use_validator) { |
| if (use_validator) |
| output_surface_->InitWithSingleOverlayValidator(); |
| |
| renderer_ = |
| make_scoped_ptr(new OverlayInfoRendererGL(&renderer_client_, |
| &settings_, |
| output_surface_.get(), |
| resource_provider_.get())); |
| } |
| |
| void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); } |
| |
| RendererSettings settings_; |
| FakeOutputSurfaceClient output_surface_client_; |
| scoped_ptr<OverlayOutputSurface> output_surface_; |
| FakeRendererClient renderer_client_; |
| scoped_ptr<ResourceProvider> resource_provider_; |
| scoped_ptr<OverlayInfoRendererGL> renderer_; |
| scoped_refptr<TestContextProvider> provider_; |
| MockOverlayScheduler scheduler_; |
| }; |
| |
| TEST_F(GLRendererWithOverlaysTest, OverlayQuadNotDrawn) { |
| bool use_validator = true; |
| Init(use_validator); |
| renderer_->set_expect_overlays(true); |
| gfx::Rect viewport_rect(16, 16); |
| |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| |
| CreateFullscreenCandidateQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| |
| RenderPassList pass_list; |
| pass_list.push_back(pass.Pass()); |
| |
| // Candidate pass was taken out and extra skipped pass added, |
| // so only draw 2 quads. |
| EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(2); |
| EXPECT_CALL(scheduler_, |
| Schedule(1, |
| gfx::OVERLAY_TRANSFORM_NONE, |
| _, |
| kOverlayRect, |
| BoundingRect(kUVTopLeft, kUVBottomRight))).Times(1); |
| renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false); |
| |
| SwapBuffers(); |
| |
| Mock::VerifyAndClearExpectations(renderer_.get()); |
| Mock::VerifyAndClearExpectations(&scheduler_); |
| } |
| |
| TEST_F(GLRendererWithOverlaysTest, OccludedQuadDrawn) { |
| bool use_validator = true; |
| Init(use_validator); |
| renderer_->set_expect_overlays(false); |
| gfx::Rect viewport_rect(16, 16); |
| |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| |
| CreateFullscreenCandidateQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| |
| RenderPassList pass_list; |
| pass_list.push_back(pass.Pass()); |
| |
| // 3 quads in the pass, all should draw. |
| EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3); |
| EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0); |
| renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false); |
| |
| SwapBuffers(); |
| |
| Mock::VerifyAndClearExpectations(renderer_.get()); |
| Mock::VerifyAndClearExpectations(&scheduler_); |
| } |
| |
| TEST_F(GLRendererWithOverlaysTest, NoValidatorNoOverlay) { |
| bool use_validator = false; |
| Init(use_validator); |
| renderer_->set_expect_overlays(false); |
| gfx::Rect viewport_rect(16, 16); |
| |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| |
| CreateFullscreenCandidateQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| CreateFullscreenCheckeredQuad(resource_provider_.get(), |
| pass->shared_quad_state_list.back(), |
| pass.get()); |
| |
| RenderPassList pass_list; |
| pass_list.push_back(pass.Pass()); |
| |
| // Should see no overlays. |
| EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3); |
| EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0); |
| renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false); |
| |
| SwapBuffers(); |
| |
| Mock::VerifyAndClearExpectations(renderer_.get()); |
| Mock::VerifyAndClearExpectations(&scheduler_); |
| } |
| |
| TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturned) { |
| bool use_validator = true; |
| Init(use_validator); |
| renderer_->set_expect_overlays(true); |
| |
| ResourceProvider::ResourceId resource1 = |
| CreateResource(resource_provider_.get()); |
| ResourceProvider::ResourceId resource2 = |
| CreateResource(resource_provider_.get()); |
| |
| scoped_ptr<RenderPass> pass = CreateRenderPass(); |
| RenderPassList pass_list; |
| pass_list.push_back(pass.Pass()); |
| |
| DirectRenderer::DrawingFrame frame1; |
| frame1.render_passes_in_draw_order = &pass_list; |
| frame1.overlay_list.resize(2); |
| OverlayCandidate& overlay1 = frame1.overlay_list.back(); |
| overlay1.resource_id = resource1; |
| overlay1.plane_z_order = 1; |
| |
| DirectRenderer::DrawingFrame frame2; |
| frame2.render_passes_in_draw_order = &pass_list; |
| frame2.overlay_list.resize(2); |
| OverlayCandidate& overlay2 = frame2.overlay_list.back(); |
| overlay2.resource_id = resource2; |
| overlay2.plane_z_order = 1; |
| |
| EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1); |
| renderer_->BeginDrawingFrame(&frame1); |
| renderer_->FinishDrawingFrame(&frame1); |
| EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1)); |
| EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2)); |
| SwapBuffers(); |
| Mock::VerifyAndClearExpectations(&scheduler_); |
| |
| EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1); |
| renderer_->BeginDrawingFrame(&frame2); |
| renderer_->FinishDrawingFrame(&frame2); |
| EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1)); |
| EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2)); |
| SwapBuffers(); |
| EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1)); |
| Mock::VerifyAndClearExpectations(&scheduler_); |
| |
| EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1); |
| renderer_->BeginDrawingFrame(&frame1); |
| renderer_->FinishDrawingFrame(&frame1); |
| EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1)); |
| EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2)); |
| SwapBuffers(); |
| EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2)); |
| Mock::VerifyAndClearExpectations(&scheduler_); |
| |
| // No overlays, release the resource. |
| EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0); |
| DirectRenderer::DrawingFrame frame3; |
| frame3.render_passes_in_draw_order = &pass_list; |
| renderer_->set_expect_overlays(false); |
| renderer_->BeginDrawingFrame(&frame3); |
| renderer_->FinishDrawingFrame(&frame3); |
| EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1)); |
| EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2)); |
| SwapBuffers(); |
| EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1)); |
| Mock::VerifyAndClearExpectations(&scheduler_); |
| |
| // Use the same buffer twice. |
| renderer_->set_expect_overlays(true); |
| EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1); |
| renderer_->BeginDrawingFrame(&frame1); |
| renderer_->FinishDrawingFrame(&frame1); |
| EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1)); |
| SwapBuffers(); |
| Mock::VerifyAndClearExpectations(&scheduler_); |
| |
| EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1); |
| renderer_->BeginDrawingFrame(&frame1); |
| renderer_->FinishDrawingFrame(&frame1); |
| EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1)); |
| SwapBuffers(); |
| EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1)); |
| Mock::VerifyAndClearExpectations(&scheduler_); |
| |
| EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0); |
| renderer_->set_expect_overlays(false); |
| renderer_->BeginDrawingFrame(&frame3); |
| renderer_->FinishDrawingFrame(&frame3); |
| EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1)); |
| SwapBuffers(); |
| EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1)); |
| Mock::VerifyAndClearExpectations(&scheduler_); |
| } |
| |
| } // namespace |
| } // namespace cc |