From 877996b0753f32b67fac2835756d23f476e72f10 Mon Sep 17 00:00:00 2001 From: brianderson Date: Tue, 20 Oct 2015 13:35:31 -0700 Subject: cc: Plumbing for BeginFrameSource based on Surfaces This patch makes a stable decision about which Display a Surface belongs to and notifies the corresponding SurfaceFactoryClient of the BeginFrameSource belonging to that Display. The stable decision is based on the sorted order of Display pointers that the Surface currently belongs to. This is only plumbing - the actual endpoints (BeginFrameSource to use and what to do with that BeginFrameSource) still need to be hooked up. R=jbauman,mithro BUG=401331, 471411 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1304063014 Cr-Commit-Position: refs/heads/master@{#355140} --- cc/surfaces/display.cc | 29 ++- cc/surfaces/display.h | 7 + cc/surfaces/display_scheduler.cc | 4 + cc/surfaces/display_scheduler.h | 7 + cc/surfaces/display_unittest.cc | 45 +++- cc/surfaces/onscreen_display_client.cc | 5 +- cc/surfaces/onscreen_display_client.h | 7 +- cc/surfaces/surface.cc | 31 +++ cc/surfaces/surface.h | 9 + cc/surfaces/surface_aggregator.cc | 46 +++- cc/surfaces/surface_aggregator.h | 18 +- cc/surfaces/surface_aggregator_perftest.cc | 12 +- cc/surfaces/surface_aggregator_unittest.cc | 290 ++++++++++++++++++++++++-- cc/surfaces/surface_display_output_surface.cc | 7 + cc/surfaces/surface_display_output_surface.h | 2 + cc/surfaces/surface_factory.cc | 6 + cc/surfaces/surface_factory.h | 5 + cc/surfaces/surface_factory_client.h | 12 ++ cc/surfaces/surface_factory_unittest.cc | 115 ++++++---- cc/surfaces/surface_hittest_unittest.cc | 2 + cc/surfaces/surface_unittest.cc | 128 +++++++++++- cc/surfaces/surfaces_pixeltest.cc | 20 +- 22 files changed, 723 insertions(+), 84 deletions(-) (limited to 'cc/surfaces') diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc index dd776fb..7cd9d6d 100644 --- a/cc/surfaces/display.cc +++ b/cc/surfaces/display.cc @@ -131,8 +131,8 @@ void Display::InitializeRenderer() { // overlays. bool output_partial_list = renderer_->Capabilities().using_partial_swap && !output_surface_->GetOverlayCandidateValidator(); - aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get(), - output_partial_list)); + aggregator_.reset(new SurfaceAggregator( + this, manager_, resource_provider_.get(), output_partial_list)); } void Display::DidLoseOutputSurface() { @@ -150,6 +150,31 @@ void Display::UpdateRootSurfaceResourcesLocked() { scheduler_->SetRootSurfaceResourcesLocked(root_surface_resources_locked); } +void Display::AddSurface(Surface* surface) { + // Checking for the output_surface ensures Display::Initialize has been + // called and that scheduler_ won't change its value. + DCHECK(output_surface_); + + // WebView's HardwareRenderer will never have a scheduler. + if (!scheduler_) + return; + + surface->AddBeginFrameSource(scheduler_->begin_frame_source_for_children()); +} + +void Display::RemoveSurface(Surface* surface) { + // Checking for the output_surface ensures Display::Initialize has been + // called and that scheduler_ won't change its value. + DCHECK(output_surface_); + + // WebView's HardwareRenderer will never have a scheduler. + if (!scheduler_) + return; + + surface->RemoveBeginFrameSource( + scheduler_->begin_frame_source_for_children()); +} + bool Display::DrawAndSwap() { TRACE_EVENT0("cc", "Display::DrawAndSwap"); diff --git a/cc/surfaces/display.h b/cc/surfaces/display.h index b849b46..3873d13 100644 --- a/cc/surfaces/display.h +++ b/cc/surfaces/display.h @@ -11,6 +11,7 @@ #include "cc/output/output_surface_client.h" #include "cc/output/renderer.h" #include "cc/resources/returned_resource.h" +#include "cc/scheduler/begin_frame_source.h" #include "cc/surfaces/display_scheduler.h" #include "cc/surfaces/surface_aggregator.h" #include "cc/surfaces/surface_id.h" @@ -28,6 +29,7 @@ class Size; namespace cc { +class BeginFrameSource; class DirectRenderer; class DisplayClient; class OutputSurface; @@ -46,6 +48,7 @@ class TextureMailboxDeleter; class CC_SURFACES_EXPORT Display : public DisplaySchedulerClient, public OutputSurfaceClient, public RendererClient, + public SurfaceAggregatorClient, public SurfaceDamageObserver { public: Display(DisplayClient* client, @@ -66,6 +69,10 @@ class CC_SURFACES_EXPORT Display : public DisplaySchedulerClient, SurfaceId CurrentSurfaceId(); + // SurfaceAggregatorClient implementation + void AddSurface(Surface* surface) override; + void RemoveSurface(Surface* surface) override; + // DisplaySchedulerClient implementation. bool DrawAndSwap() override; diff --git a/cc/surfaces/display_scheduler.cc b/cc/surfaces/display_scheduler.cc index 033632e..feb84ea 100644 --- a/cc/surfaces/display_scheduler.cc +++ b/cc/surfaces/display_scheduler.cc @@ -33,6 +33,10 @@ DisplayScheduler::DisplayScheduler(DisplaySchedulerClient* client, begin_frame_source_->AddObserver(this); begin_frame_deadline_closure_ = base::Bind( &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr()); + + // TODO(tansell): Set this to something useful. + begin_frame_source_for_children_ = SyntheticBeginFrameSource::Create( + task_runner, BeginFrameArgs::DefaultInterval()); } DisplayScheduler::~DisplayScheduler() { diff --git a/cc/surfaces/display_scheduler.h b/cc/surfaces/display_scheduler.h index 4ffc6ea..7b043c0 100644 --- a/cc/surfaces/display_scheduler.h +++ b/cc/surfaces/display_scheduler.h @@ -48,6 +48,10 @@ class CC_SURFACES_EXPORT DisplayScheduler : public BeginFrameObserverBase { // BeginFrameObserverBase implementation bool OnBeginFrameDerivedImpl(const BeginFrameArgs& args) override; + BeginFrameSource* begin_frame_source_for_children() { + return begin_frame_source_for_children_.get(); + } + protected: base::TimeTicks DesiredBeginFrameDeadlineTime(); virtual void ScheduleBeginFrameDeadline(); @@ -64,6 +68,9 @@ class CC_SURFACES_EXPORT DisplayScheduler : public BeginFrameObserverBase { base::CancelableClosure begin_frame_deadline_task_; base::TimeTicks begin_frame_deadline_task_time_; + // TODO(tansell): Set this to something useful. + scoped_ptr begin_frame_source_for_children_; + bool output_surface_lost_; bool root_surface_resources_locked_; diff --git a/cc/surfaces/display_unittest.cc b/cc/surfaces/display_unittest.cc index 6058f15..7b82d96 100644 --- a/cc/surfaces/display_unittest.cc +++ b/cc/surfaces/display_unittest.cc @@ -26,9 +26,21 @@ using testing::AnyNumber; namespace cc { namespace { -class EmptySurfaceFactoryClient : public SurfaceFactoryClient { +class FakeSurfaceFactoryClient : public SurfaceFactoryClient { public: + FakeSurfaceFactoryClient() : begin_frame_source_(nullptr) {} + void ReturnResources(const ReturnedResourceArray& resources) override {} + + void SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source) override { + begin_frame_source_ = begin_frame_source; + } + + BeginFrameSource* begin_frame_source() { return begin_frame_source_; } + + private: + BeginFrameSource* begin_frame_source_; }; class TestSoftwareOutputDevice : public SoftwareOutputDevice { @@ -42,7 +54,7 @@ class TestSoftwareOutputDevice : public SoftwareOutputDevice { class DisplayTest : public testing::Test { public: DisplayTest() - : factory_(&manager_, &empty_client_), + : factory_(&manager_, &surface_factory_client_), software_output_device_(nullptr), task_runner_(new base::NullTaskRunner) {} @@ -73,7 +85,7 @@ class DisplayTest : public testing::Test { } SurfaceManager manager_; - EmptySurfaceFactoryClient empty_client_; + FakeSurfaceFactoryClient surface_factory_client_; SurfaceFactory factory_; TestSoftwareOutputDevice* software_output_device_; scoped_ptr output_surface_; @@ -103,7 +115,9 @@ class TestDisplayScheduler : public DisplayScheduler { damaged(false), display_resized_(false), has_new_root_surface(false), - swapped(false) {} + swapped(false) { + begin_frame_source_for_children_.reset(new FakeBeginFrameSource); + } ~TestDisplayScheduler() override {} @@ -136,6 +150,29 @@ void CopyCallback(bool* called, scoped_ptr result) { *called = true; } +// Verify Display responds to SurfaceAggregatorClient methods properly. +TEST_F(DisplayTest, DisplayAsSurfaceAggregatorClient) { + SetUpContext(nullptr); + TestDisplayClient client; + RendererSettings settings; + Display display(&client, &manager_, shared_bitmap_manager_.get(), nullptr, + settings); + + TestDisplayScheduler scheduler(&display, &fake_begin_frame_source_, + task_runner_.get()); + display.Initialize(output_surface_.Pass(), &scheduler); + + SurfaceId surface_id(6); + factory_.Create(surface_id); + Surface* surface = manager_.GetSurfaceForId(surface_id); + + EXPECT_EQ(nullptr, surface_factory_client_.begin_frame_source()); + display.AddSurface(surface); + EXPECT_NE(nullptr, surface_factory_client_.begin_frame_source()); + display.RemoveSurface(surface); + EXPECT_EQ(nullptr, surface_factory_client_.begin_frame_source()); +} + // Check that frame is damaged and swapped only under correct conditions. TEST_F(DisplayTest, DisplayDamaged) { SetUpContext(nullptr); diff --git a/cc/surfaces/onscreen_display_client.cc b/cc/surfaces/onscreen_display_client.cc index 29a2a7a..067f443 100644 --- a/cc/surfaces/onscreen_display_client.cc +++ b/cc/surfaces/onscreen_display_client.cc @@ -22,15 +22,14 @@ OnscreenDisplayClient::OnscreenDisplayClient( const RendererSettings& settings, scoped_refptr task_runner) : output_surface_(output_surface.Pass()), + task_runner_(task_runner), display_(new Display(this, manager, bitmap_manager, gpu_memory_buffer_manager, settings)), - task_runner_(task_runner), output_surface_lost_(false), - disable_display_vsync_(settings.disable_display_vsync) { -} + disable_display_vsync_(settings.disable_display_vsync) {} OnscreenDisplayClient::~OnscreenDisplayClient() { } diff --git a/cc/surfaces/onscreen_display_client.h b/cc/surfaces/onscreen_display_client.h index 4c4245d..3094306 100644 --- a/cc/surfaces/onscreen_display_client.h +++ b/cc/surfaces/onscreen_display_client.h @@ -53,11 +53,14 @@ class CC_SURFACES_EXPORT OnscreenDisplayClient protected: scoped_ptr output_surface_; - scoped_ptr display_; + // Be careful of destruction order: + // Display depends on DisplayScheduler depends on *BeginFrameSource + // depends on TaskRunner. + scoped_refptr task_runner_; scoped_ptr synthetic_frame_source_; scoped_ptr unthrottled_frame_source_; scoped_ptr scheduler_; - scoped_refptr task_runner_; + scoped_ptr display_; SurfaceDisplayOutputSurface* surface_display_output_surface_; bool output_surface_lost_; bool disable_display_vsync_; diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc index e3b0f5e..0ffd522 100644 --- a/cc/surfaces/surface.cc +++ b/cc/surfaces/surface.cc @@ -35,6 +35,9 @@ Surface::~Surface() { } if (!draw_callback_.is_null()) draw_callback_.Run(SurfaceDrawStatus::DRAW_SKIPPED); + + if (factory_) + factory_->SetBeginFrameSource(surface_id_, NULL); } void Surface::QueueFrame(scoped_ptr frame, @@ -175,6 +178,34 @@ void Surface::SatisfyDestructionDependencies( destruction_dependencies_.end()); } +void Surface::AddBeginFrameSource(BeginFrameSource* begin_frame_source) { + DCHECK(base::STLIsSorted(begin_frame_sources_)); + DCHECK(!ContainsValue(begin_frame_sources_, begin_frame_source)) + << begin_frame_source; + begin_frame_sources_.insert(begin_frame_source); + UpdatePrimaryBeginFrameSource(); +} + +void Surface::RemoveBeginFrameSource(BeginFrameSource* begin_frame_source) { + size_t erase_count = begin_frame_sources_.erase(begin_frame_source); + DCHECK_EQ(1u, erase_count); + UpdatePrimaryBeginFrameSource(); +} + +void Surface::UpdatePrimaryBeginFrameSource() { + // Ensure the BeginFrameSources are sorted so our we make a stable decision + // regarding which source is primary. + // TODO(brianderson): Do something smarter based on coverage instead. + DCHECK(base::STLIsSorted(begin_frame_sources_)); + + BeginFrameSource* primary_source = nullptr; + if (!begin_frame_sources_.empty()) + primary_source = *begin_frame_sources_.begin(); + + if (factory_) + factory_->SetBeginFrameSource(surface_id_, primary_source); +} + void Surface::ClearCopyRequests() { if (current_frame_) { for (const auto& render_pass : diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h index 8ef332e..18ca744 100644 --- a/cc/surfaces/surface.h +++ b/cc/surfaces/surface.h @@ -6,6 +6,7 @@ #define CC_SURFACES_SURFACE_H_ #include +#include #include #include "base/callback.h" @@ -80,8 +81,12 @@ class CC_SURFACES_EXPORT Surface { bool destroyed() const { return destroyed_; } void set_destroyed(bool destroyed) { destroyed_ = destroyed; } + void AddBeginFrameSource(BeginFrameSource* begin_frame_source); + void RemoveBeginFrameSource(BeginFrameSource* begin_frame_source); + private: void ClearCopyRequests(); + void UpdatePrimaryBeginFrameSource(); SurfaceId surface_id_; base::WeakPtr factory_; @@ -91,6 +96,10 @@ class CC_SURFACES_EXPORT Surface { bool destroyed_; std::vector destruction_dependencies_; + // This surface may have multiple BeginFrameSources if it is + // on multiple Displays. + std::set begin_frame_sources_; + std::vector referenced_surfaces_; DrawCallback draw_callback_; diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc index 902f836..967f496 100644 --- a/cc/surfaces/surface_aggregator.cc +++ b/cc/surfaces/surface_aggregator.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/containers/hash_tables.h" #include "base/logging.h" +#include "base/stl_util.h" #include "base/trace_event/trace_event.h" #include "cc/base/math_util.h" #include "cc/output/compositor_frame.h" @@ -40,17 +41,23 @@ void MoveMatchingRequests( } // namespace -SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager, +SurfaceAggregator::SurfaceAggregator(SurfaceAggregatorClient* client, + SurfaceManager* manager, ResourceProvider* provider, bool aggregate_only_damaged) - : manager_(manager), + : client_(client), + manager_(manager), provider_(provider), next_render_pass_id_(1), aggregate_only_damaged_(aggregate_only_damaged) { DCHECK(manager_); } -SurfaceAggregator::~SurfaceAggregator() {} +SurfaceAggregator::~SurfaceAggregator() { + // Notify client of all surfaces being removed. + contained_surfaces_.clear(); + ProcessAddedAndRemovedSurfaces(); +} // Create a clip rect for an aggregated quad from the original clip rect and // the clip rect from the surface it's on. @@ -135,14 +142,18 @@ int SurfaceAggregator::ChildIdForSurface(Surface* surface) { } } +gfx::Rect SurfaceAggregator::DamageRectForSurface( + const Surface* surface, + const RenderPass& source, + const gfx::Rect& full_rect) const { + auto it = previous_contained_surfaces_.find(surface->surface_id()); + if (it == previous_contained_surfaces_.end()) + return full_rect; -gfx::Rect SurfaceAggregator::DamageRectForSurface(const Surface* surface, - const RenderPass& source, - const gfx::Rect& full_rect) { - int previous_index = previous_contained_surfaces_[surface->surface_id()]; + int previous_index = it->second; if (previous_index == surface->frame_index()) return gfx::Rect(); - else if (previous_index == surface->frame_index() - 1) + if (previous_index == surface->frame_index() - 1) return source.damage_rect; return full_rect; } @@ -450,9 +461,10 @@ void SurfaceAggregator::CopyPasses(const DelegatedFrameData* frame_data, } } -void SurfaceAggregator::RemoveUnreferencedChildren() { +void SurfaceAggregator::ProcessAddedAndRemovedSurfaces() { for (const auto& surface : previous_contained_surfaces_) { if (!contained_surfaces_.count(surface.first)) { + // Release resources of removed surface. SurfaceToResourceChildIdMap::iterator it = surface_id_to_resource_child_id_.find(surface.first); if (it != surface_id_to_resource_child_id_.end()) { @@ -460,9 +472,21 @@ void SurfaceAggregator::RemoveUnreferencedChildren() { surface_id_to_resource_child_id_.erase(it); } + // Notify client of removed surface. Surface* surface_ptr = manager_->GetSurfaceForId(surface.first); - if (surface_ptr) + if (surface_ptr) { surface_ptr->RunDrawCallbacks(SurfaceDrawStatus::DRAW_SKIPPED); + client_->RemoveSurface(surface_ptr); + } + } + } + + for (const auto& surface : contained_surfaces_) { + if (!previous_contained_surfaces_.count(surface.first)) { + // Notify client of added surface. + Surface* surface_ptr = manager_->GetSurfaceForId(surface.first); + if (surface_ptr) + client_->AddSurface(surface_ptr); } } } @@ -606,7 +630,7 @@ scoped_ptr SurfaceAggregator::Aggregate(SurfaceId surface_id) { dest_pass_list_->back()->damage_rect = root_damage_rect_; dest_pass_list_ = NULL; - RemoveUnreferencedChildren(); + ProcessAddedAndRemovedSurfaces(); contained_surfaces_.swap(previous_contained_surfaces_); contained_surfaces_.clear(); diff --git a/cc/surfaces/surface_aggregator.h b/cc/surfaces/surface_aggregator.h index 1ff4a45..738aeec 100644 --- a/cc/surfaces/surface_aggregator.h +++ b/cc/surfaces/surface_aggregator.h @@ -25,11 +25,20 @@ class Surface; class SurfaceDrawQuad; class SurfaceManager; +class CC_SURFACES_EXPORT SurfaceAggregatorClient { + public: + virtual ~SurfaceAggregatorClient() {} + + virtual void AddSurface(Surface* surface) = 0; + virtual void RemoveSurface(Surface* surface) = 0; +}; + class CC_SURFACES_EXPORT SurfaceAggregator { public: typedef base::hash_map SurfaceIndexMap; - SurfaceAggregator(SurfaceManager* manager, + SurfaceAggregator(SurfaceAggregatorClient* client, + SurfaceManager* manager, ResourceProvider* provider, bool aggregate_only_damaged); ~SurfaceAggregator(); @@ -79,13 +88,16 @@ class CC_SURFACES_EXPORT SurfaceAggregator { // Remove Surfaces that were referenced before but aren't currently // referenced from the ResourceProvider. - void RemoveUnreferencedChildren(); + // Also notifies SurfaceAggregatorClient of newly added and removed + // child surfaces. + void ProcessAddedAndRemovedSurfaces(); int ChildIdForSurface(Surface* surface); gfx::Rect DamageRectForSurface(const Surface* surface, const RenderPass& source, - const gfx::Rect& full_rect); + const gfx::Rect& full_rect) const; + SurfaceAggregatorClient* client_; // Outlives this class. SurfaceManager* manager_; ResourceProvider* provider_; diff --git a/cc/surfaces/surface_aggregator_perftest.cc b/cc/surfaces/surface_aggregator_perftest.cc index 2960c44..95085c3 100644 --- a/cc/surfaces/surface_aggregator_perftest.cc +++ b/cc/surfaces/surface_aggregator_perftest.cc @@ -24,6 +24,14 @@ namespace { class EmptySurfaceFactoryClient : public SurfaceFactoryClient { public: void ReturnResources(const ReturnedResourceArray& resources) override {} + void SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source) override {} +}; + +class EmptySurfaceAggregatorClient : public SurfaceAggregatorClient { + public: + void AddSurface(Surface* surface) override {} + void RemoveSurface(Surface* surface) override {} }; class SurfaceAggregatorPerfTest : public testing::Test { @@ -44,7 +52,8 @@ class SurfaceAggregatorPerfTest : public testing::Test { bool optimize_damage, bool full_damage, const std::string& name) { - aggregator_.reset(new SurfaceAggregator(&manager_, resource_provider_.get(), + aggregator_.reset(new SurfaceAggregator(&surface_aggregator_client_, + &manager_, resource_provider_.get(), optimize_damage)); for (int i = 1; i <= num_surfaces; i++) { factory_.Create(SurfaceId(i)); @@ -139,6 +148,7 @@ class SurfaceAggregatorPerfTest : public testing::Test { scoped_ptr shared_bitmap_manager_; scoped_ptr resource_provider_; scoped_ptr aggregator_; + EmptySurfaceAggregatorClient surface_aggregator_client_; LapTimer timer_; }; diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc index bee479c..63aba46 100644 --- a/cc/surfaces/surface_aggregator_unittest.cc +++ b/cc/surfaces/surface_aggregator_unittest.cc @@ -43,20 +43,47 @@ gfx::Size SurfaceSize() { class EmptySurfaceFactoryClient : public SurfaceFactoryClient { public: void ReturnResources(const ReturnedResourceArray& resources) override {} + void WillDrawSurface(SurfaceId id, const gfx::Rect& damage_rect) override { last_surface_id_ = id; last_damage_rect_ = damage_rect; } + void SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source) override {} + gfx::Rect last_damage_rect_; SurfaceId last_surface_id_; }; +class FakeSurfaceAggregatorClient : public SurfaceAggregatorClient { + public: + void AddSurface(Surface* surface) override { + EXPECT_FALSE(HasSurface(surface)); + surfaces_.insert(surface); + } + + void RemoveSurface(Surface* surface) override { + EXPECT_TRUE(HasSurface(surface)); + surfaces_.erase(surface); + } + + bool HasSurface(Surface* surface) const { + return surfaces_.count(surface) != 0; + } + + private: + std::set surfaces_; +}; + class SurfaceAggregatorTest : public testing::Test { public: explicit SurfaceAggregatorTest(bool use_damage_rect) : factory_(&manager_, &empty_client_), - aggregator_(&manager_, NULL, use_damage_rect) {} + aggregator_(&surface_aggregator_client_, + &manager_, + NULL, + use_damage_rect) {} SurfaceAggregatorTest() : SurfaceAggregatorTest(false) {} @@ -64,14 +91,20 @@ class SurfaceAggregatorTest : public testing::Test { SurfaceManager manager_; EmptySurfaceFactoryClient empty_client_; SurfaceFactory factory_; + FakeSurfaceAggregatorClient surface_aggregator_client_; SurfaceAggregator aggregator_; }; TEST_F(SurfaceAggregatorTest, ValidSurfaceNoFrame) { SurfaceId one_id(7); factory_.Create(one_id); + Surface* surface = manager_.GetSurfaceForId(one_id); + + EXPECT_FALSE(surface_aggregator_client_.HasSurface(surface)); scoped_ptr frame = aggregator_.Aggregate(one_id); EXPECT_FALSE(frame); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(surface)); + factory_.Destroy(one_id); } @@ -88,6 +121,7 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest { SurfaceAggregatorTest::SetUp(); root_surface_id_ = allocator_.GenerateId(); factory_.Create(root_surface_id_); + root_surface_ = manager_.GetSurfaceForId(root_surface_id_); } void TearDown() override { @@ -158,6 +192,7 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest { protected: SurfaceId root_surface_id_; + Surface* root_surface_; SurfaceIdAllocator allocator_; SurfaceIdAllocator child_allocator_; }; @@ -172,7 +207,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) { SubmitCompositorFrame(passes, arraysize(passes), root_surface_id_); SurfaceId ids[] = {root_surface_id_}; + + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); // Check that WillDrawSurface was called. EXPECT_EQ(gfx::Rect(SurfaceSize()), empty_client_.last_damage_rect_); @@ -182,6 +220,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) { TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) { SurfaceId embedded_surface_id = allocator_.GenerateId(); factory_.Create(embedded_surface_id); + Surface* embedded_surface = manager_.GetSurfaceForId(embedded_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), test::Quad::SolidColorQuad(SK_ColorBLUE)}; @@ -196,9 +236,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) { SubmitCompositorFrame(passes, arraysize(passes), root_surface_id_); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(embedded_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -232,7 +278,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) { SubmitCompositorFrame(passes, arraysize(passes), root_surface_id_); SurfaceId ids[] = {root_surface_id_}; + + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); } // This tests very simple embedding. root_surface has a frame containing a few @@ -242,6 +291,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) { TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) { SurfaceId embedded_surface_id = allocator_.GenerateId(); factory_.Create(embedded_surface_id); + Surface* embedded_surface = manager_.GetSurfaceForId(embedded_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; test::Pass embedded_passes[] = { @@ -257,6 +308,9 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) { SubmitCompositorFrame(root_passes, arraysize(root_passes), root_surface_id_); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); + test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE), test::Quad::SolidColorQuad(SK_ColorGREEN), test::Quad::SolidColorQuad(SK_ColorBLACK)}; @@ -266,12 +320,17 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) { AggregateAndVerify( expected_passes, arraysize(expected_passes), ids, arraysize(ids)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(embedded_surface)); + factory_.Destroy(embedded_surface_id); } TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) { SurfaceId embedded_surface_id = allocator_.GenerateId(); factory_.Create(embedded_surface_id); + Surface* embedded_surface = manager_.GetSurfaceForId(embedded_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; test::Pass embedded_passes[] = { @@ -291,9 +350,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) { SubmitCompositorFrame(root_passes, arraysize(root_passes), root_surface_id_); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(embedded_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -330,6 +395,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) { TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) { SurfaceId embedded_surface_id = allocator_.GenerateId(); factory_.Create(embedded_surface_id); + Surface* embedded_surface = manager_.GetSurfaceForId(embedded_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)}; test::Pass embedded_passes[] = { @@ -370,9 +437,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) { SurfaceFactory::DrawCallback()); } + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(embedded_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -420,6 +493,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) { TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) { SurfaceId embedded_surface_id = child_allocator_.GenerateId(); factory_.Create(embedded_surface_id); + Surface* embedded_surface = manager_.GetSurfaceForId(embedded_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); RenderPassId pass_ids[] = {RenderPassId(1, 1), RenderPassId(1, 2), RenderPassId(1, 3)}; @@ -448,9 +523,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) { SubmitCompositorFrame(root_passes, arraysize(root_passes), root_surface_id_); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(embedded_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(embedded_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -570,8 +651,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) { test::Pass expected_passes[] = { test::Pass(expected_quads, arraysize(expected_quads))}; SurfaceId ids[] = {root_surface_id_, InvalidSurfaceId()}; + + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); AggregateAndVerify( expected_passes, arraysize(expected_passes), ids, arraysize(ids)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); } // Tests a reference to a valid surface with no submitted frame. This quad @@ -579,6 +663,9 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) { TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) { SurfaceId surface_with_no_frame_id = allocator_.GenerateId(); factory_.Create(surface_with_no_frame_id); + Surface* surface_with_no_frame = + manager_.GetSurfaceForId(surface_with_no_frame_id); + test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN), test::Quad::SurfaceQuad(surface_with_no_frame_id, 1.f), test::Quad::SolidColorQuad(SK_ColorBLUE)}; @@ -591,8 +678,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) { test::Pass expected_passes[] = { test::Pass(expected_quads, arraysize(expected_quads))}; SurfaceId ids[] = {root_surface_id_, surface_with_no_frame_id}; + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(surface_with_no_frame)); AggregateAndVerify( expected_passes, arraysize(expected_passes), ids, arraysize(ids)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(surface_with_no_frame)); factory_.Destroy(surface_with_no_frame_id); } @@ -609,14 +700,18 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) { test::Pass expected_passes[] = { test::Pass(expected_quads, arraysize(expected_quads))}; SurfaceId ids[] = {root_surface_id_}; + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); AggregateAndVerify( expected_passes, arraysize(expected_passes), ids, arraysize(ids)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); } // Tests a more complex cycle with one intermediate surface. TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) { SurfaceId child_surface_id = allocator_.GenerateId(); factory_.Create(child_surface_id); + Surface* child_surface = manager_.GetSurfaceForId(child_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_surface)); test::Quad parent_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE), test::Quad::SurfaceQuad(child_surface_id, 1.f), @@ -648,8 +743,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) { test::Pass expected_passes[] = { test::Pass(expected_quads, arraysize(expected_quads))}; SurfaceId ids[] = {root_surface_id_, child_surface_id}; + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_surface)); AggregateAndVerify( expected_passes, arraysize(expected_passes), ids, arraysize(ids)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); factory_.Destroy(child_surface_id); } @@ -658,6 +757,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) { TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) { SurfaceId child_surface_id = allocator_.GenerateId(); factory_.Create(child_surface_id); + Surface* child_surface = manager_.GetSurfaceForId(child_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_surface)); RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)}; test::Quad child_quad[][1] = {{test::Quad::SolidColorQuad(SK_ColorGREEN)}, @@ -680,9 +781,16 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) { SubmitCompositorFrame(parent_passes, arraysize(parent_passes), root_surface_id_); + + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -780,6 +888,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { RenderPassId pass_id(1, 1); SurfaceId grandchild_surface_id = allocator_.GenerateId(); factory_.Create(grandchild_surface_id); + Surface* grandchild_surface = manager_.GetSurfaceForId(grandchild_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(grandchild_surface)); scoped_ptr grandchild_pass = RenderPass::Create(); gfx::Rect output_rect(SurfaceSize()); gfx::Rect damage_rect(SurfaceSize()); @@ -792,6 +902,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { SurfaceId child_one_surface_id = allocator_.GenerateId(); factory_.Create(child_one_surface_id); + Surface* child_one_surface = manager_.GetSurfaceForId(child_one_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_one_surface)); scoped_ptr child_one_pass = RenderPass::Create(); child_one_pass->SetNew( @@ -810,6 +922,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { SurfaceId child_two_surface_id = allocator_.GenerateId(); factory_.Create(child_two_surface_id); + Surface* child_two_surface = manager_.GetSurfaceForId(child_two_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_two_surface)); scoped_ptr child_two_pass = RenderPass::Create(); child_two_pass->SetNew( @@ -843,9 +957,19 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { QueuePassAsFrame(root_pass.Pass(), root_surface_id_); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(grandchild_surface)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_one_surface)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_two_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(grandchild_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_one_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_two_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -891,8 +1015,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) { TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { // Innermost child surface. SurfaceId child_surface_id = allocator_.GenerateId(); + factory_.Create(child_surface_id); + Surface* child_surface = manager_.GetSurfaceForId(child_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_surface)); { - factory_.Create(child_surface_id); RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)}; test::Quad child_quads[][1] = { {test::Quad::SolidColorQuad(SK_ColorGREEN)}, @@ -932,8 +1058,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { // Middle child surface. SurfaceId middle_surface_id = allocator_.GenerateId(); + factory_.Create(middle_surface_id); + Surface* middle_surface = manager_.GetSurfaceForId(middle_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(middle_surface)); { - factory_.Create(middle_surface_id); test::Quad middle_quads[] = { test::Quad::SurfaceQuad(child_surface_id, 1.f)}; test::Pass middle_passes[] = { @@ -996,9 +1124,17 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) { factory_.SubmitCompositorFrame(root_surface_id_, root_frame.Pass(), SurfaceFactory::DrawCallback()); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(middle_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(middle_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -1102,6 +1238,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { SurfaceId child_surface_id = allocator_.GenerateId(); factory_.Create(child_surface_id); + Surface* child_surface = manager_.GetSurfaceForId(child_surface_id); factory_.SubmitCompositorFrame(child_surface_id, child_frame.Pass(), SurfaceFactory::DrawCallback()); @@ -1128,6 +1265,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { SurfaceId parent_surface_id = allocator_.GenerateId(); factory_.Create(parent_surface_id); + Surface* parent_surface = manager_.GetSurfaceForId(parent_surface_id); factory_.SubmitCompositorFrame(parent_surface_id, parent_surface_frame.Pass(), SurfaceFactory::DrawCallback()); @@ -1163,9 +1301,17 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { factory_.SubmitCompositorFrame(root_surface_id_, root_frame.Pass(), SurfaceFactory::DrawCallback()); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(parent_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(parent_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -1200,9 +1346,17 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { factory_.SubmitCompositorFrame(child_surface_id, child_frame.Pass(), SurfaceFactory::DrawCallback()); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(parent_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(parent_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -1262,9 +1416,17 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { factory_.SubmitCompositorFrame(root_surface_id_, root_frame.Pass(), SurfaceFactory::DrawCallback()); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(parent_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(parent_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -1283,9 +1445,17 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { // No Surface changed, so no damage should be given. { + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(parent_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(parent_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -1302,10 +1472,18 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) { // SetFullDamageRectForSurface should cause the entire output to be // marked as damaged. { + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(parent_surface)); + aggregator_.SetFullDamageForSurface(root_surface_id_); scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(parent_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -1334,6 +1512,7 @@ class SurfaceAggregatorPartialSwapTest TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { SurfaceId child_surface_id = allocator_.GenerateId(); factory_.Create(child_surface_id); + Surface* child_surface = manager_.GetSurfaceForId(child_surface_id); // The child surface has two quads, one with a visible rect of 13,13 4x4 and // the other other with a visible rect of 10,10 2x2 (relative to root target // space). @@ -1379,9 +1558,15 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { SubmitPassListAsFrame(root_surface_id_, &root_pass_list); } + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -1414,9 +1599,15 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { } { + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -1469,9 +1660,15 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { } { + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -1493,9 +1690,15 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) { } { + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + scoped_ptr aggregated_frame = aggregator_.Aggregate(root_surface_id_); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface_)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + ASSERT_TRUE(aggregated_frame); ASSERT_TRUE(aggregated_frame->delegated_frame_data); @@ -1524,8 +1727,9 @@ class SurfaceAggregatorWithResourcesTest : public testing::Test { resource_provider_ = FakeResourceProvider::Create( output_surface_.get(), shared_bitmap_manager_.get()); - aggregator_.reset( - new SurfaceAggregator(&manager_, resource_provider_.get(), false)); + aggregator_.reset(new SurfaceAggregator(&surface_aggregator_client_, + &manager_, resource_provider_.get(), + false)); } protected: @@ -1535,6 +1739,7 @@ class SurfaceAggregatorWithResourcesTest : public testing::Test { scoped_ptr shared_bitmap_manager_; scoped_ptr resource_provider_; scoped_ptr aggregator_; + FakeSurfaceAggregatorClient surface_aggregator_client_; }; class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient { @@ -1550,6 +1755,9 @@ class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient { return returned_resources_; } + void SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source) override {} + private: ReturnedResourceArray returned_resources_; @@ -1609,21 +1817,30 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) { SurfaceFactory factory(&manager_, &client); SurfaceId surface_id(7u); factory.Create(surface_id); + Surface* surface = manager_.GetSurfaceForId(surface_id); ResourceId ids[] = {11, 12, 13}; SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(), &factory, surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(surface)); + scoped_ptr frame = aggregator_->Aggregate(surface_id); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(surface)); + // Nothing should be available to be returned yet. EXPECT_TRUE(client.returned_resources().empty()); SubmitCompositorFrameWithResources(NULL, 0u, true, SurfaceId(), &factory, surface_id); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(surface)); + frame = aggregator_->Aggregate(surface_id); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(surface)); + ASSERT_EQ(3u, client.returned_resources().size()); ResourceId returned_ids[3]; for (size_t i = 0; i < 3; ++i) { @@ -1639,6 +1856,7 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) { SurfaceFactory factory(&manager_, &client); SurfaceId surface_id(7u); factory.Create(surface_id); + Surface* surface = manager_.GetSurfaceForId(surface_id); scoped_ptr frame_data(new DelegatedFrameData); scoped_ptr pass = RenderPass::Create(); @@ -1655,9 +1873,13 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) { factory.SubmitCompositorFrame(surface_id, frame.Pass(), SurfaceFactory::DrawCallback()); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(surface)); + scoped_ptr returned_frame = aggregator_->Aggregate(surface_id); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(surface)); + // Nothing should be available to be returned yet. EXPECT_TRUE(client.returned_resources().empty()); @@ -1672,29 +1894,44 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) { TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) { ResourceTrackingSurfaceFactoryClient client; SurfaceFactory factory(&manager_, &client); - SurfaceId surface_id(7u); - factory.Create(surface_id); - SurfaceId surface_id2(8u); - factory.Create(surface_id2); + SurfaceId surface1_id(7u); + factory.Create(surface1_id); + Surface* surface1 = manager_.GetSurfaceForId(surface1_id); + + SurfaceId surface2_id(8u); + factory.Create(surface2_id); + Surface* surface2 = manager_.GetSurfaceForId(surface2_id); ResourceId ids[] = {11, 12, 13}; SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(), - &factory, surface_id); + &factory, surface1_id); ResourceId ids2[] = {14, 15, 16}; SubmitCompositorFrameWithResources(ids2, arraysize(ids2), true, SurfaceId(), - &factory, surface_id2); + &factory, surface2_id); - scoped_ptr frame = aggregator_->Aggregate(surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(surface1)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(surface2)); + + scoped_ptr frame = aggregator_->Aggregate(surface1_id); + + EXPECT_TRUE(surface_aggregator_client_.HasSurface(surface1)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(surface2)); SubmitCompositorFrameWithResources(NULL, 0, true, SurfaceId(), &factory, - surface_id); + surface1_id); // Nothing should be available to be returned yet. EXPECT_TRUE(client.returned_resources().empty()); - frame = aggregator_->Aggregate(surface_id2); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(surface1)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(surface2)); + + frame = aggregator_->Aggregate(surface2_id); - // surface_id wasn't referenced, so its resources should be returned. + EXPECT_FALSE(surface_aggregator_client_.HasSurface(surface1)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(surface2)); + + // surface1_id wasn't referenced, so its resources should be returned. ASSERT_EQ(3u, client.returned_resources().size()); ResourceId returned_ids[3]; for (size_t i = 0; i < 3; ++i) { @@ -1703,8 +1940,8 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) { EXPECT_THAT(returned_ids, testing::WhenSorted(testing::ElementsAreArray(ids))); EXPECT_EQ(3u, resource_provider_->num_resources()); - factory.Destroy(surface_id); - factory.Destroy(surface_id2); + factory.Destroy(surface1_id); + factory.Destroy(surface2_id); } // Ensure that aggregator completely ignores Surfaces that reference invalid @@ -1714,10 +1951,13 @@ TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) { SurfaceFactory factory(&manager_, &client); SurfaceId root_surface_id(7u); factory.Create(root_surface_id); + Surface* root_surface = manager_.GetSurfaceForId(root_surface_id); SurfaceId middle_surface_id(8u); factory.Create(middle_surface_id); + Surface* middle_surface = manager_.GetSurfaceForId(middle_surface_id); SurfaceId child_surface_id(9u); factory.Create(child_surface_id); + Surface* child_surface = manager_.GetSurfaceForId(child_surface_id); ResourceId ids[] = {14, 15, 16}; SubmitCompositorFrameWithResources(ids, arraysize(ids), true, SurfaceId(), @@ -1733,9 +1973,17 @@ TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) { middle_surface_id, &factory, root_surface_id); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(root_surface)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(middle_surface)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_surface)); + scoped_ptr frame; frame = aggregator_->Aggregate(root_surface_id); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(middle_surface)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_surface)); + RenderPassList* pass_list = &frame->delegated_frame_data->render_pass_list; ASSERT_EQ(1u, pass_list->size()); EXPECT_EQ(1u, pass_list->back()->shared_quad_state_list.size()); @@ -1745,8 +1993,16 @@ TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) { child_surface_id, &factory, middle_surface_id); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(middle_surface)); + EXPECT_FALSE(surface_aggregator_client_.HasSurface(child_surface)); + frame = aggregator_->Aggregate(root_surface_id); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(root_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(middle_surface)); + EXPECT_TRUE(surface_aggregator_client_.HasSurface(child_surface)); + pass_list = &frame->delegated_frame_data->render_pass_list; ASSERT_EQ(1u, pass_list->size()); EXPECT_EQ(3u, pass_list->back()->shared_quad_state_list.size()); diff --git a/cc/surfaces/surface_display_output_surface.cc b/cc/surfaces/surface_display_output_surface.cc index ed26b49..9e9ade7 100644 --- a/cc/surfaces/surface_display_output_surface.cc +++ b/cc/surfaces/surface_display_output_surface.cc @@ -93,6 +93,13 @@ void SurfaceDisplayOutputSurface::ReturnResources( client_->ReclaimResources(&ack); } +void SurfaceDisplayOutputSurface::SetBeginFrameSource( + SurfaceId surface_id, + BeginFrameSource* begin_frame_source) { + // TODO(tansell): Hook this up. + NOTIMPLEMENTED(); +} + void SurfaceDisplayOutputSurface::SwapBuffersComplete(SurfaceDrawStatus drawn) { if (client_ && !display_client_->output_surface_lost()) client_->DidSwapBuffersComplete(); diff --git a/cc/surfaces/surface_display_output_surface.h b/cc/surfaces/surface_display_output_surface.h index 2cdaadc..5dbbbe0 100644 --- a/cc/surfaces/surface_display_output_surface.h +++ b/cc/surfaces/surface_display_output_surface.h @@ -45,6 +45,8 @@ class CC_SURFACES_EXPORT SurfaceDisplayOutputSurface // SurfaceFactoryClient implementation. void ReturnResources(const ReturnedResourceArray& resources) override; + void SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source) override; private: void SwapBuffersComplete(SurfaceDrawStatus drawn); diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc index 72ebdc4..b71994e 100644 --- a/cc/surfaces/surface_factory.cc +++ b/cc/surfaces/surface_factory.cc @@ -27,6 +27,7 @@ SurfaceFactory::~SurfaceFactory() { << " entries in map on destruction."; } DestroyAll(); + client_->SetBeginFrameSource(SurfaceId(), nullptr); } void SurfaceFactory::DestroyAll() { @@ -49,6 +50,11 @@ void SurfaceFactory::Destroy(SurfaceId surface_id) { manager_->Destroy(surface_map_.take_and_erase(it)); } +void SurfaceFactory::SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source) { + client_->SetBeginFrameSource(surface_id, begin_frame_source); +} + void SurfaceFactory::SubmitCompositorFrame(SurfaceId surface_id, scoped_ptr frame, const DrawCallback& callback) { diff --git a/cc/surfaces/surface_factory.h b/cc/surfaces/surface_factory.h index 762d5a2..1347728 100644 --- a/cc/surfaces/surface_factory.h +++ b/cc/surfaces/surface_factory.h @@ -23,6 +23,7 @@ class Size; } namespace cc { +class BeginFrameSource; class CopyOutputRequest; class Surface; class SurfaceFactoryClient; @@ -46,6 +47,10 @@ class CC_SURFACES_EXPORT SurfaceFactory void Create(SurfaceId surface_id); void Destroy(SurfaceId surface_id); void DestroyAll(); + + void SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source); + // A frame can only be submitted to a surface created by this factory, // although the frame may reference surfaces created by other factories. // The callback is called the first time this frame is used to draw, or if diff --git a/cc/surfaces/surface_factory_client.h b/cc/surfaces/surface_factory_client.h index c2a04af..e79b185 100644 --- a/cc/surfaces/surface_factory_client.h +++ b/cc/surfaces/surface_factory_client.h @@ -12,6 +12,9 @@ namespace cc { +class BeginFrameSource; +struct SurfaceId; + class CC_SURFACES_EXPORT SurfaceFactoryClient { public: virtual ~SurfaceFactoryClient() {} @@ -20,6 +23,15 @@ class CC_SURFACES_EXPORT SurfaceFactoryClient { virtual void WillDrawSurface(SurfaceId surface_id, const gfx::Rect& damage_rect) {} + + // This allows the SurfaceFactory to tell it's client what BeginFrameSource + // to use for a given surface_id. + // If there are multiple active surface_ids, it is the client's + // responsibility to pick or distribute the correct BeginFrameSource. + // If surface_id is null, then all BeginFrameSources previously + // set by this function should be invalidated. + virtual void SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source) = 0; }; } // namespace cc diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc index 9629a4e..d516aa3 100644 --- a/cc/surfaces/surface_factory_unittest.cc +++ b/cc/surfaces/surface_factory_unittest.cc @@ -12,6 +12,7 @@ #include "cc/surfaces/surface_factory.h" #include "cc/surfaces/surface_factory_client.h" #include "cc/surfaces/surface_manager.h" +#include "cc/test/scheduler_test_common.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/size.h" @@ -20,7 +21,7 @@ namespace { class TestSurfaceFactoryClient : public SurfaceFactoryClient { public: - TestSurfaceFactoryClient() {} + TestSurfaceFactoryClient() : begin_frame_source_(nullptr) {} ~TestSurfaceFactoryClient() override {} void ReturnResources(const ReturnedResourceArray& resources) override { @@ -28,27 +29,36 @@ class TestSurfaceFactoryClient : public SurfaceFactoryClient { returned_resources_.end(), resources.begin(), resources.end()); } + void SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source) override { + begin_frame_source_ = begin_frame_source; + } + const ReturnedResourceArray& returned_resources() const { return returned_resources_; } void clear_returned_resources() { returned_resources_.clear(); } + BeginFrameSource* begin_frame_source() const { return begin_frame_source_; } + private: ReturnedResourceArray returned_resources_; + BeginFrameSource* begin_frame_source_; DISALLOW_COPY_AND_ASSIGN(TestSurfaceFactoryClient); }; class SurfaceFactoryTest : public testing::Test { public: - SurfaceFactoryTest() : factory_(&manager_, &client_), surface_id_(3) { - factory_.Create(surface_id_); + SurfaceFactoryTest() + : factory_(new SurfaceFactory(&manager_, &client_)), surface_id_(3) { + factory_->Create(surface_id_); } ~SurfaceFactoryTest() override { if (!surface_id_.is_null()) - factory_.Destroy(surface_id_); + factory_->Destroy(surface_id_); } void SubmitCompositorFrameWithResources(ResourceId* resource_ids, @@ -62,8 +72,8 @@ class SurfaceFactoryTest : public testing::Test { } scoped_ptr frame(new CompositorFrame); frame->delegated_frame_data = frame_data.Pass(); - factory_.SubmitCompositorFrame(surface_id_, frame.Pass(), - SurfaceFactory::DrawCallback()); + factory_->SubmitCompositorFrame(surface_id_, frame.Pass(), + SurfaceFactory::DrawCallback()); } void UnrefResources(ResourceId* ids_to_unref, @@ -76,7 +86,7 @@ class SurfaceFactoryTest : public testing::Test { resource.count = counts_to_unref[i]; unref_array.push_back(resource); } - factory_.UnrefResources(unref_array); + factory_->UnrefResources(unref_array); } void CheckReturnedResourcesMatchExpected(ResourceId* expected_returned_ids, @@ -95,14 +105,14 @@ class SurfaceFactoryTest : public testing::Test { void RefCurrentFrameResources() { Surface* surface = manager_.GetSurfaceForId(surface_id_); - factory_.RefResources( + factory_->RefResources( surface->GetEligibleFrame()->delegated_frame_data->resource_list); } protected: SurfaceManager manager_; TestSurfaceFactoryClient client_; - SurfaceFactory factory_; + scoped_ptr factory_; SurfaceId surface_id_; }; @@ -374,17 +384,17 @@ TEST_F(SurfaceFactoryTest, ResourceLifetime) { TEST_F(SurfaceFactoryTest, BlankNoIndexIncrement) { SurfaceId surface_id(6); - factory_.Create(surface_id); + factory_->Create(surface_id); Surface* surface = manager_.GetSurfaceForId(surface_id); ASSERT_NE(nullptr, surface); EXPECT_EQ(2, surface->frame_index()); scoped_ptr frame(new CompositorFrame); frame->delegated_frame_data.reset(new DelegatedFrameData); - factory_.SubmitCompositorFrame(surface_id, frame.Pass(), - SurfaceFactory::DrawCallback()); + factory_->SubmitCompositorFrame(surface_id, frame.Pass(), + SurfaceFactory::DrawCallback()); EXPECT_EQ(2, surface->frame_index()); - factory_.Destroy(surface_id); + factory_->Destroy(surface_id); } void DrawCallback(uint32* execute_count, @@ -397,7 +407,7 @@ void DrawCallback(uint32* execute_count, // Tests doing a DestroyAll before shutting down the factory; TEST_F(SurfaceFactoryTest, DestroyAll) { SurfaceId id(7); - factory_.Create(id); + factory_->Create(id); scoped_ptr frame_data(new DelegatedFrameData); TransferableResource resource; @@ -409,25 +419,25 @@ TEST_F(SurfaceFactoryTest, DestroyAll) { uint32 execute_count = 0; SurfaceDrawStatus drawn = SurfaceDrawStatus::DRAW_SKIPPED; - factory_.SubmitCompositorFrame( + factory_->SubmitCompositorFrame( id, frame.Pass(), base::Bind(&DrawCallback, &execute_count, &drawn)); surface_id_ = SurfaceId(); - factory_.DestroyAll(); + factory_->DestroyAll(); EXPECT_EQ(1u, execute_count); EXPECT_EQ(SurfaceDrawStatus::DRAW_SKIPPED, drawn); } TEST_F(SurfaceFactoryTest, DestroySequence) { SurfaceId id2(5); - factory_.Create(id2); + factory_->Create(id2); manager_.RegisterSurfaceIdNamespace(0); // Check that waiting before the sequence is satisfied works. manager_.GetSurfaceForId(id2) ->AddDestructionDependency(SurfaceSequence(0, 4)); - factory_.Destroy(id2); + factory_->Destroy(id2); scoped_ptr frame_data(new DelegatedFrameData); scoped_ptr frame(new CompositorFrame); @@ -435,16 +445,16 @@ TEST_F(SurfaceFactoryTest, DestroySequence) { frame->metadata.satisfies_sequences.push_back(4); frame->delegated_frame_data = frame_data.Pass(); DCHECK(manager_.GetSurfaceForId(id2)); - factory_.SubmitCompositorFrame(surface_id_, frame.Pass(), - SurfaceFactory::DrawCallback()); + factory_->SubmitCompositorFrame(surface_id_, frame.Pass(), + SurfaceFactory::DrawCallback()); DCHECK(!manager_.GetSurfaceForId(id2)); // Check that waiting after the sequence is satisfied works. - factory_.Create(id2); + factory_->Create(id2); DCHECK(manager_.GetSurfaceForId(id2)); manager_.GetSurfaceForId(id2) ->AddDestructionDependency(SurfaceSequence(0, 6)); - factory_.Destroy(id2); + factory_->Destroy(id2); DCHECK(!manager_.GetSurfaceForId(id2)); } @@ -453,12 +463,12 @@ TEST_F(SurfaceFactoryTest, DestroySequence) { TEST_F(SurfaceFactoryTest, InvalidIdNamespace) { uint32_t id_namespace = 9u; SurfaceId id(5); - factory_.Create(id); + factory_->Create(id); manager_.RegisterSurfaceIdNamespace(id_namespace); manager_.GetSurfaceForId(id) ->AddDestructionDependency(SurfaceSequence(id_namespace, 4)); - factory_.Destroy(id); + factory_->Destroy(id); // Verify the dependency has prevented the surface from getting destroyed. EXPECT_TRUE(manager_.GetSurfaceForId(id)); @@ -472,7 +482,7 @@ TEST_F(SurfaceFactoryTest, InvalidIdNamespace) { TEST_F(SurfaceFactoryTest, DestroyCycle) { SurfaceId id2(5); - factory_.Create(id2); + factory_->Create(id2); manager_.RegisterSurfaceIdNamespace(0); @@ -487,10 +497,10 @@ TEST_F(SurfaceFactoryTest, DestroyCycle) { frame_data->render_pass_list.push_back(render_pass.Pass()); scoped_ptr frame(new CompositorFrame); frame->delegated_frame_data = frame_data.Pass(); - factory_.SubmitCompositorFrame(id2, frame.Pass(), - SurfaceFactory::DrawCallback()); + factory_->SubmitCompositorFrame(id2, frame.Pass(), + SurfaceFactory::DrawCallback()); } - factory_.Destroy(id2); + factory_->Destroy(id2); // Give surface_id_ a frame that references id2. { @@ -500,10 +510,10 @@ TEST_F(SurfaceFactoryTest, DestroyCycle) { frame_data->render_pass_list.push_back(render_pass.Pass()); scoped_ptr frame(new CompositorFrame); frame->delegated_frame_data = frame_data.Pass(); - factory_.SubmitCompositorFrame(surface_id_, frame.Pass(), - SurfaceFactory::DrawCallback()); + factory_->SubmitCompositorFrame(surface_id_, frame.Pass(), + SurfaceFactory::DrawCallback()); } - factory_.Destroy(surface_id_); + factory_->Destroy(surface_id_); EXPECT_TRUE(manager_.GetSurfaceForId(id2)); // surface_id_ should be retained by reference from id2. EXPECT_TRUE(manager_.GetSurfaceForId(surface_id_)); @@ -534,8 +544,8 @@ TEST_F(SurfaceFactoryTest, DuplicateCopyRequest) { frame_data->render_pass_list.push_back(render_pass.Pass()); scoped_ptr frame(new CompositorFrame); frame->delegated_frame_data = frame_data.Pass(); - factory_.SubmitCompositorFrame(surface_id_, frame.Pass(), - SurfaceFactory::DrawCallback()); + factory_->SubmitCompositorFrame(surface_id_, frame.Pass(), + SurfaceFactory::DrawCallback()); } void* source1 = &source1; void* source2 = &source2; @@ -546,7 +556,7 @@ TEST_F(SurfaceFactoryTest, DuplicateCopyRequest) { base::Bind(&CopyRequestTestCallback, &called1)); request->set_source(source1); - factory_.RequestCopyOfSurface(surface_id_, request.Pass()); + factory_->RequestCopyOfSurface(surface_id_, request.Pass()); EXPECT_FALSE(called1); bool called2 = false; @@ -554,7 +564,7 @@ TEST_F(SurfaceFactoryTest, DuplicateCopyRequest) { base::Bind(&CopyRequestTestCallback, &called2)); request->set_source(source2); - factory_.RequestCopyOfSurface(surface_id_, request.Pass()); + factory_->RequestCopyOfSurface(surface_id_, request.Pass()); // Callbacks have different sources so neither should be called. EXPECT_FALSE(called1); EXPECT_FALSE(called2); @@ -564,18 +574,49 @@ TEST_F(SurfaceFactoryTest, DuplicateCopyRequest) { base::Bind(&CopyRequestTestCallback, &called3)); request->set_source(source1); - factory_.RequestCopyOfSurface(surface_id_, request.Pass()); + factory_->RequestCopyOfSurface(surface_id_, request.Pass()); // Two callbacks are from source1, so the first should be called. EXPECT_TRUE(called1); EXPECT_FALSE(called2); EXPECT_FALSE(called3); - factory_.Destroy(surface_id_); + factory_->Destroy(surface_id_); surface_id_ = SurfaceId(); EXPECT_TRUE(called1); EXPECT_TRUE(called2); EXPECT_TRUE(called3); } +// Verifies BFS is forwarded to the client. +TEST_F(SurfaceFactoryTest, SetBeginFrameSource) { + FakeBeginFrameSource bfs1; + FakeBeginFrameSource bfs2; + EXPECT_EQ(nullptr, client_.begin_frame_source()); + factory_->SetBeginFrameSource(surface_id_, &bfs1); + EXPECT_EQ(&bfs1, client_.begin_frame_source()); + factory_->SetBeginFrameSource(surface_id_, &bfs2); + EXPECT_EQ(&bfs2, client_.begin_frame_source()); + factory_->SetBeginFrameSource(surface_id_, nullptr); + EXPECT_EQ(nullptr, client_.begin_frame_source()); +} + +TEST_F(SurfaceFactoryTest, BeginFrameSourceRemovedOnFactoryDestruction) { + FakeBeginFrameSource bfs; + factory_->SetBeginFrameSource(surface_id_, &bfs); + EXPECT_EQ(&bfs, client_.begin_frame_source()); + + // Prevent the Surface from being destroyed when we destroy the factory. + manager_.RegisterSurfaceIdNamespace(0); + manager_.GetSurfaceForId(surface_id_) + ->AddDestructionDependency(SurfaceSequence(0, 4)); + + surface_id_ = SurfaceId(); + factory_->DestroyAll(); + + EXPECT_EQ(&bfs, client_.begin_frame_source()); + factory_.reset(); + EXPECT_EQ(nullptr, client_.begin_frame_source()); +} + } // namespace } // namespace cc diff --git a/cc/surfaces/surface_hittest_unittest.cc b/cc/surfaces/surface_hittest_unittest.cc index ac9e3bc..92c61b8 100644 --- a/cc/surfaces/surface_hittest_unittest.cc +++ b/cc/surfaces/surface_hittest_unittest.cc @@ -55,6 +55,8 @@ void RunTests(SurfaceManager* manager, TestCase* tests, size_t test_count) { class EmptySurfaceFactoryClient : public SurfaceFactoryClient { public: void ReturnResources(const ReturnedResourceArray& resources) override {} + void SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source) override {} }; void CreateSharedQuadState(RenderPass* pass, diff --git a/cc/surfaces/surface_unittest.cc b/cc/surfaces/surface_unittest.cc index 42fd55f..5a9b744 100644 --- a/cc/surfaces/surface_unittest.cc +++ b/cc/surfaces/surface_unittest.cc @@ -4,16 +4,36 @@ #include "cc/surfaces/surface.h" #include "cc/surfaces/surface_factory.h" +#include "cc/surfaces/surface_factory_client.h" #include "cc/surfaces/surface_manager.h" +#include "cc/test/scheduler_test_common.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/size.h" namespace cc { namespace { +class FakeSurfaceFactoryClient : public SurfaceFactoryClient { + public: + FakeSurfaceFactoryClient() : begin_frame_source_(nullptr) {} + + void ReturnResources(const ReturnedResourceArray& resources) override {} + + void SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source) override { + begin_frame_source_ = begin_frame_source; + } + + BeginFrameSource* begin_frame_source() { return begin_frame_source_; } + + private: + BeginFrameSource* begin_frame_source_; +}; + TEST(SurfaceTest, SurfaceLifetime) { SurfaceManager manager; - SurfaceFactory factory(&manager, NULL); + FakeSurfaceFactoryClient surface_factory_client; + SurfaceFactory factory(&manager, &surface_factory_client); SurfaceId surface_id(6); { @@ -25,5 +45,111 @@ TEST(SurfaceTest, SurfaceLifetime) { EXPECT_EQ(NULL, manager.GetSurfaceForId(surface_id)); } +TEST(SurfaceTest, StableBeginFrameSourceIndependentOfOrderAdded) { + SurfaceManager manager; + FakeSurfaceFactoryClient surface_factory_client; + SurfaceFactory factory(&manager, &surface_factory_client); + + SurfaceId surface_id(6); + factory.Create(surface_id); + Surface* surface = manager.GetSurfaceForId(surface_id); + + FakeBeginFrameSource bfs1; + FakeBeginFrameSource bfs2; + FakeBeginFrameSource bfs3; + + // Order 1. + surface->AddBeginFrameSource(&bfs1); + surface->AddBeginFrameSource(&bfs2); + surface->AddBeginFrameSource(&bfs3); + BeginFrameSource* bfs_order1 = surface_factory_client.begin_frame_source(); + // Make sure one of the provided sources was chosen. + EXPECT_TRUE(&bfs1 == bfs_order1 || &bfs2 == bfs_order1 || + &bfs3 == bfs_order1); + surface->RemoveBeginFrameSource(&bfs1); + surface->RemoveBeginFrameSource(&bfs2); + surface->RemoveBeginFrameSource(&bfs3); + EXPECT_EQ(nullptr, surface_factory_client.begin_frame_source()); + + // Order 2. + surface->AddBeginFrameSource(&bfs1); + surface->AddBeginFrameSource(&bfs3); + surface->AddBeginFrameSource(&bfs2); + BeginFrameSource* bfs_order2 = surface_factory_client.begin_frame_source(); + // Verify choice is same as before. + EXPECT_EQ(bfs_order1, bfs_order2); + surface->RemoveBeginFrameSource(&bfs1); + surface->RemoveBeginFrameSource(&bfs2); + surface->RemoveBeginFrameSource(&bfs3); + EXPECT_EQ(nullptr, surface_factory_client.begin_frame_source()); + + // Order 3. + surface->AddBeginFrameSource(&bfs2); + surface->AddBeginFrameSource(&bfs1); + surface->AddBeginFrameSource(&bfs3); + BeginFrameSource* bfs_order3 = surface_factory_client.begin_frame_source(); + // Verify choice is same as before. + EXPECT_EQ(bfs_order2, bfs_order3); + surface->RemoveBeginFrameSource(&bfs1); + surface->RemoveBeginFrameSource(&bfs2); + surface->RemoveBeginFrameSource(&bfs3); + EXPECT_EQ(nullptr, surface_factory_client.begin_frame_source()); + + // Order 4. + surface->AddBeginFrameSource(&bfs2); + surface->AddBeginFrameSource(&bfs3); + surface->AddBeginFrameSource(&bfs1); + BeginFrameSource* bfs_order4 = surface_factory_client.begin_frame_source(); + // Verify choice is same as before. + EXPECT_EQ(bfs_order3, bfs_order4); + surface->RemoveBeginFrameSource(&bfs1); + surface->RemoveBeginFrameSource(&bfs2); + surface->RemoveBeginFrameSource(&bfs3); + EXPECT_EQ(nullptr, surface_factory_client.begin_frame_source()); + + // Order 5. + surface->AddBeginFrameSource(&bfs3); + surface->AddBeginFrameSource(&bfs1); + surface->AddBeginFrameSource(&bfs2); + BeginFrameSource* bfs_order5 = surface_factory_client.begin_frame_source(); + // Verify choice is same as before. + EXPECT_EQ(bfs_order4, bfs_order5); + surface->RemoveBeginFrameSource(&bfs1); + surface->RemoveBeginFrameSource(&bfs2); + surface->RemoveBeginFrameSource(&bfs3); + EXPECT_EQ(nullptr, surface_factory_client.begin_frame_source()); + + // Order 6. + surface->AddBeginFrameSource(&bfs3); + surface->AddBeginFrameSource(&bfs2); + surface->AddBeginFrameSource(&bfs1); + BeginFrameSource* bfs_order6 = surface_factory_client.begin_frame_source(); + // Verify choice is same as before. + EXPECT_EQ(bfs_order5, bfs_order6); + surface->RemoveBeginFrameSource(&bfs1); + surface->RemoveBeginFrameSource(&bfs2); + surface->RemoveBeginFrameSource(&bfs3); + EXPECT_EQ(nullptr, surface_factory_client.begin_frame_source()); +} + +TEST(SurfaceTest, BeginFrameSourceRemovedOnSurfaceDestruction) { + SurfaceManager manager; + FakeSurfaceFactoryClient surface_factory_client; + SurfaceFactory factory(&manager, &surface_factory_client); + FakeBeginFrameSource bfs; + + SurfaceId surface_id(6); + factory.Create(surface_id); + Surface* surface = manager.GetSurfaceForId(surface_id); + surface->AddBeginFrameSource(&bfs); + + BeginFrameSource* bfs_before = surface_factory_client.begin_frame_source(); + factory.Destroy(surface_id); + BeginFrameSource* bfs_after = surface_factory_client.begin_frame_source(); + + EXPECT_EQ(&bfs, bfs_before); + EXPECT_EQ(nullptr, bfs_after); +} + } // namespace } // namespace cc diff --git a/cc/surfaces/surfaces_pixeltest.cc b/cc/surfaces/surfaces_pixeltest.cc index a584f7c..f0903f2 100644 --- a/cc/surfaces/surfaces_pixeltest.cc +++ b/cc/surfaces/surfaces_pixeltest.cc @@ -24,6 +24,14 @@ namespace { class EmptySurfaceFactoryClient : public SurfaceFactoryClient { public: void ReturnResources(const ReturnedResourceArray& resources) override {} + void SetBeginFrameSource(SurfaceId surface_id, + BeginFrameSource* begin_frame_source) override {} +}; + +class EmptySurfaceAggregatorClient : public SurfaceAggregatorClient { + public: + void AddSurface(Surface* surface) override {} + void RemoveSurface(Surface* surface) override {} }; class SurfacesPixelTest : public RendererPixelTest { @@ -83,7 +91,9 @@ TEST_F(SurfacesPixelTest, DrawSimpleFrame) { factory_.SubmitCompositorFrame(root_surface_id, root_frame.Pass(), SurfaceFactory::DrawCallback()); - SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true); + EmptySurfaceAggregatorClient surface_aggregator_client; + SurfaceAggregator aggregator(&surface_aggregator_client, &manager_, + resource_provider_.get(), true); scoped_ptr aggregated_frame = aggregator.Aggregate(root_surface_id); factory_.Destroy(root_surface_id); @@ -167,7 +177,9 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) { SurfaceFactory::DrawCallback()); } - SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true); + EmptySurfaceAggregatorClient surface_aggregator_client; + SurfaceAggregator aggregator(&surface_aggregator_client, &manager_, + resource_provider_.get(), true); scoped_ptr aggregated_frame = aggregator.Aggregate(root_surface_id); @@ -310,7 +322,9 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) { SurfaceFactory::DrawCallback()); } - SurfaceAggregator aggregator(&manager_, resource_provider_.get(), true); + EmptySurfaceAggregatorClient surface_aggregator_client; + SurfaceAggregator aggregator(&surface_aggregator_client, &manager_, + resource_provider_.get(), true); scoped_ptr aggregated_frame = aggregator.Aggregate(root_surface_id); -- cgit v1.1