// 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:
virtual 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.
virtual 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) {}
void InitWithSingleOverlayValidator() {
overlay_candidate_validator_.reset(new SingleOverlayValidator);
}
};
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 (QuadList::Iterator exp_iter = expected->quad_list.begin(),
act_iter = actual->quad_list.begin();
exp_iter != expected->quad_list.end();
++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, 0, false, 1, false));
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,
0,
false,
1,
false);
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 LayerTreeSettings* 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));
virtual 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.
virtual 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, 0, false, 1, false);
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()); }
LayerTreeSettings 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());
DirectRenderer::DrawingFrame frame1;
frame1.overlay_list.resize(2);
OverlayCandidate& overlay1 = frame1.overlay_list.back();
overlay1.resource_id = resource1;
overlay1.plane_z_order = 1;
DirectRenderer::DrawingFrame frame2;
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_->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_->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_->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;
renderer_->set_expect_overlays(false);
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_->FinishDrawingFrame(&frame1);
EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
SwapBuffers();
Mock::VerifyAndClearExpectations(&scheduler_);
EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
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_->FinishDrawingFrame(&frame3);
EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
SwapBuffers();
EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
Mock::VerifyAndClearExpectations(&scheduler_);
}
} // namespace
} // namespace cc