Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1028)

Side by Side Diff: cc/surfaces/compositor_frame_sink_support_unittest.cc

Issue 2802023002: Remove SurfaceFactory And SurfaceFactoryClient (Closed)
Patch Set: Address nits and rebase Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/surfaces/compositor_frame_sink_support.h" 5 #include "cc/surfaces/compositor_frame_sink_support.h"
6 6
7 #include "base/macros.h" 7 #include "base/macros.h"
8 #include "cc/output/compositor_frame.h" 8 #include "cc/output/compositor_frame.h"
9 #include "cc/output/copy_output_request.h"
10 #include "cc/output/copy_output_result.h"
11 #include "cc/resources/resource_provider.h"
9 #include "cc/surfaces/compositor_frame_sink_support_client.h" 12 #include "cc/surfaces/compositor_frame_sink_support_client.h"
10 #include "cc/surfaces/frame_sink_id.h" 13 #include "cc/surfaces/frame_sink_id.h"
11 #include "cc/surfaces/surface_id.h" 14 #include "cc/surfaces/surface_id.h"
15 #include "cc/surfaces/surface_info.h"
12 #include "cc/surfaces/surface_manager.h" 16 #include "cc/surfaces/surface_manager.h"
13 #include "cc/test/begin_frame_args_test.h" 17 #include "cc/test/begin_frame_args_test.h"
14 #include "cc/test/compositor_frame_helpers.h" 18 #include "cc/test/compositor_frame_helpers.h"
15 #include "cc/test/fake_external_begin_frame_source.h" 19 #include "cc/test/fake_external_begin_frame_source.h"
20 #include "cc/test/mock_compositor_frame_sink_support_client.h"
16 #include "testing/gmock/include/gmock/gmock.h" 21 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
18 23
19 using testing::UnorderedElementsAre; 24 using testing::UnorderedElementsAre;
20 using testing::IsEmpty; 25 using testing::IsEmpty;
21 using testing::SizeIs; 26 using testing::SizeIs;
22 using testing::Invoke; 27 using testing::Invoke;
23 using testing::_; 28 using testing::_;
24 using testing::Eq; 29 using testing::Eq;
25 30
26 namespace cc { 31 namespace cc {
32 namespace test {
27 namespace { 33 namespace {
28 34
29 constexpr FrameSinkId kDisplayFrameSink(2, 0); 35 constexpr bool kIsRoot = true;
30 constexpr FrameSinkId kParentFrameSink(3, 0); 36 constexpr bool kIsChildRoot = false;
31 constexpr FrameSinkId kChildFrameSink1(65563, 0); 37 constexpr bool kHandlesFrameSinkIdInvalidation = true;
32 constexpr FrameSinkId kChildFrameSink2(65564, 0); 38 constexpr bool kNeedsSyncPoints = true;
33 constexpr FrameSinkId kArbitraryFrameSink(1337, 7331);
34 39
35 class MockCompositorFrameSinkSupportClient 40 constexpr FrameSinkId kArbitraryFrameSinkId(1, 1);
41 constexpr FrameSinkId kAnotherArbitraryFrameSinkId(2, 2);
42 constexpr FrameSinkId kYetAnotherArbitraryFrameSinkId(3, 3);
43
44 const base::UnguessableToken kArbitraryToken = base::UnguessableToken::Create();
45 const base::UnguessableToken kArbitrarySourceId1 =
46 base::UnguessableToken::Deserialize(0xdead, 0xbeef);
47 const base::UnguessableToken kArbitrarySourceId2 =
48 base::UnguessableToken::Deserialize(0xdead, 0xbee0);
49
50 gpu::SyncToken GenTestSyncToken(int id) {
51 gpu::SyncToken token;
52 token.Set(gpu::CommandBufferNamespace::GPU_IO, 0,
53 gpu::CommandBufferId::FromUnsafeValue(id), 1);
54 return token;
55 }
56
57 class FakeCompositorFrameSinkSupportClient
36 : public CompositorFrameSinkSupportClient { 58 : public CompositorFrameSinkSupportClient {
37 public: 59 public:
38 MockCompositorFrameSinkSupportClient() { 60 FakeCompositorFrameSinkSupportClient() = default;
39 ON_CALL(*this, ReclaimResources(_)) 61 ~FakeCompositorFrameSinkSupportClient() override = default;
40 .WillByDefault(Invoke( 62
41 this, 63 void DidReceiveCompositorFrameAck(
42 &MockCompositorFrameSinkSupportClient::ReclaimResourcesInternal)); 64 const ReturnedResourceArray& resources) override {
43 ON_CALL(*this, DidReceiveCompositorFrameAck(_)) 65 InsertResources(resources);
44 .WillByDefault(Invoke(
45 this,
46 &MockCompositorFrameSinkSupportClient::ReclaimResourcesInternal));
47 } 66 }
48 67
49 ReturnedResourceArray& last_returned_resources() { 68 void OnBeginFrame(const BeginFrameArgs& args) override {}
50 return last_returned_resources_; 69
70 void ReclaimResources(const ReturnedResourceArray& resources) override {
71 InsertResources(resources);
51 } 72 }
52 73
53 // CompositorFrameSinkSupportClient implementation. 74 void WillDrawSurface(const LocalSurfaceId& local_surface_id,
54 MOCK_METHOD1(DidReceiveCompositorFrameAck, 75 const gfx::Rect& damage_rect) override {}
55 void(const ReturnedResourceArray&)); 76
56 MOCK_METHOD1(OnBeginFrame, void(const BeginFrameArgs&)); 77 void clear_returned_resources() { returned_resources_.clear(); }
57 MOCK_METHOD1(ReclaimResources, void(const ReturnedResourceArray&)); 78 const ReturnedResourceArray& returned_resources() {
58 MOCK_METHOD2(WillDrawSurface, void(const LocalSurfaceId&, const gfx::Rect&)); 79 return returned_resources_;
80 }
59 81
60 private: 82 private:
61 void ReclaimResourcesInternal(const ReturnedResourceArray& resources) { 83 void InsertResources(const ReturnedResourceArray& resources) {
62 last_returned_resources_ = resources; 84 returned_resources_.insert(returned_resources_.end(), resources.begin(),
85 resources.end());
63 } 86 }
64 87
65 ReturnedResourceArray last_returned_resources_; 88 ReturnedResourceArray returned_resources_;
89
90 DISALLOW_COPY_AND_ASSIGN(FakeCompositorFrameSinkSupportClient);
66 }; 91 };
67 92
68 std::vector<SurfaceId> empty_surface_ids() {
69 return std::vector<SurfaceId>();
70 }
71
72 SurfaceId MakeSurfaceId(const FrameSinkId& frame_sink_id, uint32_t local_id) {
73 return SurfaceId(
74 frame_sink_id,
75 LocalSurfaceId(local_id, base::UnguessableToken::Deserialize(0, 1u)));
76 }
77
78 CompositorFrame MakeCompositorFrame(
79 std::vector<SurfaceId> activation_dependencies,
80 std::vector<SurfaceId> referenced_surfaces,
81 TransferableResourceArray resource_list) {
82 CompositorFrame compositor_frame = test::MakeCompositorFrame();
83 compositor_frame.metadata.begin_frame_ack = BeginFrameAck(0, 1, 1, true);
84 compositor_frame.metadata.activation_dependencies =
85 std::move(activation_dependencies);
86 compositor_frame.metadata.referenced_surfaces =
87 std::move(referenced_surfaces);
88 compositor_frame.resource_list = std::move(resource_list);
89 return compositor_frame;
90 }
91
92 CompositorFrame MakeCompositorFrame() {
93 return MakeCompositorFrame(empty_surface_ids(), empty_surface_ids(),
94 TransferableResourceArray());
95 }
96
97 CompositorFrame MakeCompositorFrame(
98 std::vector<SurfaceId> activation_dependencies) {
99 return MakeCompositorFrame(activation_dependencies, activation_dependencies,
100 TransferableResourceArray());
101 }
102
103 CompositorFrame MakeCompositorFrame(
104 std::vector<SurfaceId> activation_dependencies,
105 std::vector<SurfaceId> referenced_surfaces) {
106 return MakeCompositorFrame(std::move(activation_dependencies),
107 std::move(referenced_surfaces),
108 TransferableResourceArray());
109 }
110
111 CompositorFrame MakeCompositorFrameWithResources(
112 std::vector<SurfaceId> activation_dependencies,
113 TransferableResourceArray resource_list) {
114 return MakeCompositorFrame(activation_dependencies, activation_dependencies,
115 std::move(resource_list));
116 }
117
118 TransferableResource MakeResource(ResourceId id,
119 ResourceFormat format,
120 uint32_t filter,
121 const gfx::Size& size) {
122 TransferableResource resource;
123 resource.id = id;
124 resource.format = format;
125 resource.filter = filter;
126 resource.size = size;
127 return resource;
128 }
129
130 } // namespace 93 } // namespace
131 94
132 class CompositorFrameSinkSupportTest : public testing::Test, 95 class CompositorFrameSinkSupportTest : public testing::Test,
133 public SurfaceObserver { 96 public SurfaceObserver {
134 public: 97 public:
135 CompositorFrameSinkSupportTest() 98 CompositorFrameSinkSupportTest()
136 : surface_manager_(SurfaceManager::LifetimeType::REFERENCES) {} 99 : support_(
137 ~CompositorFrameSinkSupportTest() override {} 100 CompositorFrameSinkSupport::Create(&fake_support_client_,
138 101 &manager_,
139 CompositorFrameSinkSupport& display_support() { return *supports_[0]; } 102 kArbitraryFrameSinkId,
140 Surface* display_surface() { 103 kIsRoot,
141 return display_support().current_surface_for_testing(); 104 kHandlesFrameSinkIdInvalidation,
142 } 105 kNeedsSyncPoints)),
143 106 local_surface_id_(3, kArbitraryToken),
144 CompositorFrameSinkSupport& parent_support() { return *supports_[1]; } 107 frame_sync_token_(GenTestSyncToken(4)),
145 Surface* parent_surface() { 108 consumer_sync_token_(GenTestSyncToken(5)) {
146 return parent_support().current_surface_for_testing(); 109 manager_.AddObserver(this);
147 } 110 }
148 const ReferencedSurfaceTracker& parent_reference_tracker() { 111 ~CompositorFrameSinkSupportTest() override {
149 return parent_support().ReferenceTrackerForTesting(); 112 manager_.RemoveObserver(this);
150 } 113 support_->EvictFrame();
151 114 }
152 CompositorFrameSinkSupport& child_support1() { return *supports_[2]; } 115
153 Surface* child_surface1() { 116 const SurfaceId& last_created_surface_id() const {
154 return child_support1().current_surface_for_testing(); 117 return last_created_surface_id_;
155 } 118 }
156 119
157 CompositorFrameSinkSupport& child_support2() { return *supports_[3]; } 120 // SurfaceObserver implementation.
158 Surface* child_surface2() { 121 void OnSurfaceCreated(const SurfaceInfo& surface_info) override {
159 return child_support2().current_surface_for_testing(); 122 last_created_surface_id_ = surface_info.id();
160 } 123 last_surface_info_ = surface_info;
161 124 }
162 CompositorFrameSinkSupport& support(int index) { return *supports_[index]; } 125 void OnSurfaceDamaged(const SurfaceId& id, bool* changed) override {
163 Surface* surface(int index) { 126 *changed = true;
164 return support(index).current_surface_for_testing(); 127 }
165 } 128
166 129 void SubmitCompositorFrameWithResources(ResourceId* resource_ids,
167 SurfaceManager& surface_manager() { return surface_manager_; } 130 size_t num_resource_ids) {
168 131 CompositorFrame frame = MakeCompositorFrame();
169 // Returns all the references where |surface_id| is the parent. 132 for (size_t i = 0u; i < num_resource_ids; ++i) {
170 const SurfaceManager::SurfaceIdSet& GetChildReferences( 133 TransferableResource resource;
171 const SurfaceId& surface_id) { 134 resource.id = resource_ids[i];
172 return surface_manager().parent_to_child_refs_[surface_id]; 135 resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
173 } 136 resource.mailbox_holder.sync_token = frame_sync_token_;
174 137 frame.resource_list.push_back(resource);
175 // Returns true if there is a temporary reference for |surface_id|. 138 }
176 bool HasTemporaryReference(const SurfaceId& surface_id) { 139 support_->SubmitCompositorFrame(local_surface_id_, std::move(frame));
177 return surface_manager().HasTemporaryReference(surface_id); 140 EXPECT_EQ(last_created_surface_id_.local_surface_id(), local_surface_id_);
178 } 141 }
179 142
180 SurfaceDependencyTracker& dependency_tracker() { 143 void UnrefResources(ResourceId* ids_to_unref,
181 return *surface_manager_.dependency_tracker(); 144 int* counts_to_unref,
182 } 145 size_t num_ids_to_unref) {
183 146 ReturnedResourceArray unref_array;
184 FakeExternalBeginFrameSource* begin_frame_source() { 147 for (size_t i = 0; i < num_ids_to_unref; ++i) {
185 return begin_frame_source_.get(); 148 ReturnedResource resource;
186 } 149 resource.sync_token = consumer_sync_token_;
187 150 resource.id = ids_to_unref[i];
188 // testing::Test: 151 resource.count = counts_to_unref[i];
189 void SetUp() override { 152 unref_array.push_back(resource);
190 testing::Test::SetUp(); 153 }
191 constexpr bool is_root = true; 154 support_->UnrefResources(unref_array);
192 constexpr bool is_child_root = false; 155 }
193 constexpr bool handles_frame_sink_id_invalidation = true; 156
194 constexpr bool needs_sync_points = true; 157 void CheckReturnedResourcesMatchExpected(ResourceId* expected_returned_ids,
195 begin_frame_source_ = 158 int* expected_returned_counts,
196 base::MakeUnique<FakeExternalBeginFrameSource>(0.f, false); 159 size_t expected_resources,
197 surface_manager_.SetDependencyTracker( 160 gpu::SyncToken expected_sync_token) {
198 base::MakeUnique<SurfaceDependencyTracker>(&surface_manager_, 161 const ReturnedResourceArray& actual_resources =
199 begin_frame_source_.get())); 162 fake_support_client_.returned_resources();
200 surface_manager_.AddObserver(this); 163 ASSERT_EQ(expected_resources, actual_resources.size());
201 supports_.push_back(CompositorFrameSinkSupport::Create( 164 for (size_t i = 0; i < expected_resources; ++i) {
202 &support_client_, &surface_manager_, kDisplayFrameSink, is_root, 165 ReturnedResource resource = actual_resources[i];
203 handles_frame_sink_id_invalidation, needs_sync_points)); 166 EXPECT_EQ(expected_sync_token, resource.sync_token);
204 supports_.push_back(CompositorFrameSinkSupport::Create( 167 EXPECT_EQ(expected_returned_ids[i], resource.id);
205 &support_client_, &surface_manager_, kParentFrameSink, is_child_root, 168 EXPECT_EQ(expected_returned_counts[i], resource.count);
206 handles_frame_sink_id_invalidation, needs_sync_points)); 169 }
207 supports_.push_back(CompositorFrameSinkSupport::Create( 170 fake_support_client_.clear_returned_resources();
208 &support_client_, &surface_manager_, kChildFrameSink1, is_child_root, 171 }
209 handles_frame_sink_id_invalidation, needs_sync_points)); 172
210 supports_.push_back(CompositorFrameSinkSupport::Create( 173 void RefCurrentFrameResources() {
211 &support_client_, &surface_manager_, kChildFrameSink2, is_child_root, 174 Surface* surface = manager_.GetSurfaceForId(
212 handles_frame_sink_id_invalidation, needs_sync_points)); 175 SurfaceId(support_->frame_sink_id(), local_surface_id_));
213 176 support_->RefResources(surface->GetActiveFrame().resource_list);
214 // Normally, the BeginFrameSource would be registered by the Display. We
215 // register it here so that BeginFrames are received by the display support,
216 // for use in the PassesOnBeginFrameAcks test. Other supports do not receive
217 // BeginFrames, since the frame sink hierarchy is not set up in this test.
218 surface_manager_.RegisterBeginFrameSource(begin_frame_source_.get(),
219 kDisplayFrameSink);
220 }
221
222 void TearDown() override {
223 surface_manager_.RemoveObserver(this);
224 surface_manager_.SetDependencyTracker(nullptr);
225 surface_manager_.UnregisterBeginFrameSource(begin_frame_source_.get());
226
227 // SurfaceDependencyTracker depends on this BeginFrameSource and so it must
228 // be destroyed AFTER the dependency tracker is destroyed.
229 begin_frame_source_.reset();
230
231 supports_.clear();
232
233 damaged_surfaces_.clear();
234 }
235
236 bool IsSurfaceDamaged(const SurfaceId& surface_id) const {
237 return damaged_surfaces_.count(surface_id) > 0;
238 }
239
240 // SurfaceObserver implementation:
241 void OnSurfaceCreated(const SurfaceInfo& surface_info) override {}
242 void OnSurfaceDamaged(const SurfaceId& surface_id, bool* changed) override {
243 damaged_surfaces_.insert(surface_id);
244 } 177 }
245 178
246 protected: 179 protected:
247 testing::NiceMock<MockCompositorFrameSinkSupportClient> support_client_; 180 SurfaceManager manager_;
248 181 FakeCompositorFrameSinkSupportClient fake_support_client_;
249 private: 182 std::unique_ptr<CompositorFrameSinkSupport> support_;
250 base::flat_set<SurfaceId> damaged_surfaces_; 183 LocalSurfaceId local_surface_id_;
251 SurfaceManager surface_manager_; 184 SurfaceId last_created_surface_id_;
252 std::unique_ptr<FakeExternalBeginFrameSource> begin_frame_source_; 185 SurfaceInfo last_surface_info_;
253 std::vector<std::unique_ptr<CompositorFrameSinkSupport>> supports_; 186
254 187 // This is the sync token submitted with the frame. It should never be
255 DISALLOW_COPY_AND_ASSIGN(CompositorFrameSinkSupportTest); 188 // returned to the client.
189 const gpu::SyncToken frame_sync_token_;
190
191 // This is the sync token returned by the consumer. It should always be
192 // returned to the client.
193 const gpu::SyncToken consumer_sync_token_;
256 }; 194 };
257 195
258 // The display root surface should have a surface reference from the top-level 196 // Tests submitting a frame with resources followed by one with no resources
259 // root added/removed when a CompositorFrame is submitted with a new SurfaceId. 197 // with no resource provider action in between.
260 TEST_F(CompositorFrameSinkSupportTest, RootSurfaceReceivesReferences) { 198 TEST_F(CompositorFrameSinkSupportTest, ResourceLifetimeSimple) {
261 const SurfaceId display_id_first = MakeSurfaceId(kDisplayFrameSink, 1); 199 ResourceId first_frame_ids[] = {1, 2, 3};
262 const SurfaceId display_id_second = MakeSurfaceId(kDisplayFrameSink, 2); 200 SubmitCompositorFrameWithResources(first_frame_ids,
263 201 arraysize(first_frame_ids));
264 // Submit a CompositorFrame for the first display root surface. 202
265 display_support().SubmitCompositorFrame(display_id_first.local_surface_id(), 203 // All of the resources submitted in the first frame are still in use at this
266 MakeCompositorFrame()); 204 // time by virtue of being in the pending frame, so none can be returned to
267 205 // the client yet.
268 // A surface reference from the top-level root is added and there shouldn't be 206 EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
269 // a temporary reference. 207 fake_support_client_.clear_returned_resources();
270 EXPECT_FALSE(HasTemporaryReference(display_id_first)); 208
271 EXPECT_THAT(GetChildReferences(surface_manager().GetRootSurfaceId()), 209 // The second frame references no resources of first frame and thus should
272 UnorderedElementsAre(display_id_first)); 210 // make all resources of first frame available to be returned.
273 211 SubmitCompositorFrameWithResources(NULL, 0);
274 // Submit a CompositorFrame for the second display root surface. 212
275 display_support().SubmitCompositorFrame(display_id_second.local_surface_id(), 213 ResourceId expected_returned_ids[] = {1, 2, 3};
276 MakeCompositorFrame()); 214 int expected_returned_counts[] = {1, 1, 1};
277 215 // Resources were never consumed so no sync token should be set.
278 // A surface reference from the top-level root to |display_id_second| should 216 CheckReturnedResourcesMatchExpected(
279 // be added and the reference to |display_root_first| removed. 217 expected_returned_ids, expected_returned_counts,
280 EXPECT_FALSE(HasTemporaryReference(display_id_second)); 218 arraysize(expected_returned_counts), gpu::SyncToken());
281 EXPECT_THAT(GetChildReferences(surface_manager().GetRootSurfaceId()), 219
282 UnorderedElementsAre(display_id_second)); 220 ResourceId third_frame_ids[] = {4, 5, 6};
283 221 SubmitCompositorFrameWithResources(third_frame_ids,
284 // Surface |display_id_first| is unreachable and should get deleted. 222 arraysize(third_frame_ids));
285 EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(display_id_first)); 223
286 } 224 // All of the resources submitted in the third frame are still in use at this
287 225 // time by virtue of being in the pending frame, so none can be returned to
288 // The parent Surface is blocked on |child_id1| and |child_id2|. 226 // the client yet.
289 TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingBlockedOnTwo) { 227 EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
290 const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); 228 fake_support_client_.clear_returned_resources();
291 const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1); 229
292 const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1); 230 // The forth frame references no resources of third frame and thus should
293 231 // make all resources of third frame available to be returned.
294 parent_support().SubmitCompositorFrame( 232 ResourceId forth_frame_ids[] = {7, 8, 9};
295 parent_id.local_surface_id(), 233 SubmitCompositorFrameWithResources(forth_frame_ids,
296 MakeCompositorFrame({child_id1, child_id2})); 234 arraysize(forth_frame_ids));
297 235
298 // parent_support is blocked on |child_id1| and |child_id2|. 236 ResourceId forth_expected_returned_ids[] = {4, 5, 6};
299 EXPECT_TRUE(dependency_tracker().has_deadline()); 237 int forth_expected_returned_counts[] = {1, 1, 1};
300 EXPECT_FALSE(parent_surface()->HasActiveFrame()); 238 // Resources were never consumed so no sync token should be set.
301 EXPECT_TRUE(parent_surface()->HasPendingFrame()); 239 CheckReturnedResourcesMatchExpected(
302 EXPECT_THAT(parent_surface()->blocking_surfaces(), 240 forth_expected_returned_ids, forth_expected_returned_counts,
303 UnorderedElementsAre(child_id1, child_id2)); 241 arraysize(forth_expected_returned_counts), gpu::SyncToken());
304 242 }
305 // Submit a CompositorFrame without any dependencies to |child_id1|. 243
306 // parent_support should now only be blocked on |child_id2|. 244 // Tests submitting a frame with resources followed by one with no resources
307 child_support1().SubmitCompositorFrame( 245 // with the resource provider holding everything alive.
308 child_id1.local_surface_id(), MakeCompositorFrame(empty_surface_ids()));
309
310 EXPECT_TRUE(dependency_tracker().has_deadline());
311 EXPECT_FALSE(parent_surface()->HasActiveFrame());
312 EXPECT_TRUE(parent_surface()->HasPendingFrame());
313 EXPECT_THAT(parent_surface()->blocking_surfaces(),
314 UnorderedElementsAre(child_id2));
315
316 // Submit a CompositorFrame without any dependencies to |child_id2|.
317 // parent_support should be activated.
318 child_support2().SubmitCompositorFrame(
319 child_id2.local_surface_id(), MakeCompositorFrame(empty_surface_ids()));
320
321 EXPECT_FALSE(dependency_tracker().has_deadline());
322 EXPECT_TRUE(parent_surface()->HasActiveFrame());
323 EXPECT_FALSE(parent_surface()->HasPendingFrame());
324 EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
325 }
326
327 // The parent Surface is blocked on |child_id2| which is blocked on |child_id3|.
328 TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingBlockedChain) {
329 const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
330 const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
331 const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
332
333 parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
334 MakeCompositorFrame({child_id1}));
335
336 // parent_support is blocked on |child_id1|.
337 EXPECT_TRUE(dependency_tracker().has_deadline());
338 EXPECT_FALSE(parent_surface()->HasActiveFrame());
339 EXPECT_TRUE(parent_surface()->HasPendingFrame());
340 EXPECT_THAT(parent_surface()->blocking_surfaces(),
341 UnorderedElementsAre(child_id1));
342 // The parent should not report damage until it activates.
343 EXPECT_FALSE(IsSurfaceDamaged(parent_id));
344
345 child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
346 MakeCompositorFrame({child_id2}));
347
348 // child_support1 should now be blocked on |child_id2|.
349 EXPECT_TRUE(dependency_tracker().has_deadline());
350 EXPECT_FALSE(child_surface1()->HasActiveFrame());
351 EXPECT_TRUE(child_surface1()->HasPendingFrame());
352 EXPECT_THAT(child_surface1()->blocking_surfaces(),
353 UnorderedElementsAre(child_id2));
354 // The parent and child should not report damage until they activate.
355 EXPECT_FALSE(IsSurfaceDamaged(parent_id));
356 EXPECT_FALSE(IsSurfaceDamaged(child_id1));
357
358 // The parent should still be blocked on |child_id1| because it's pending.
359 EXPECT_THAT(parent_surface()->blocking_surfaces(),
360 UnorderedElementsAre(child_id1));
361
362 // Submit a CompositorFrame without any dependencies to |child_id2|.
363 // parent_support should be activated.
364 child_support2().SubmitCompositorFrame(
365 child_id2.local_surface_id(), MakeCompositorFrame(empty_surface_ids()));
366
367 EXPECT_FALSE(dependency_tracker().has_deadline());
368
369 // child_surface1 should now be active.
370 EXPECT_TRUE(child_surface1()->HasActiveFrame());
371 EXPECT_FALSE(child_surface1()->HasPendingFrame());
372 EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
373
374 // parent_surface should now be active.
375 EXPECT_TRUE(parent_surface()->HasActiveFrame());
376 EXPECT_FALSE(parent_surface()->HasPendingFrame());
377 EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
378
379 // All three surfaces |parent_id|, |child_id1|, and |child_id2| should
380 // now report damage. This would trigger a new display frame.
381 EXPECT_TRUE(IsSurfaceDamaged(parent_id));
382 EXPECT_TRUE(IsSurfaceDamaged(child_id1));
383 EXPECT_TRUE(IsSurfaceDamaged(child_id2));
384 }
385
386 // parent_surface and child_surface1 are blocked on |child_id2|.
387 TEST_F(CompositorFrameSinkSupportTest, 246 TEST_F(CompositorFrameSinkSupportTest,
388 DisplayCompositorLockingTwoBlockedOnOne) { 247 ResourceLifetimeSimpleWithProviderHoldingAlive) {
389 const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); 248 ResourceId first_frame_ids[] = {1, 2, 3};
390 const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1); 249 SubmitCompositorFrameWithResources(first_frame_ids,
391 const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1); 250 arraysize(first_frame_ids));
392 251
393 parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), 252 // All of the resources submitted in the first frame are still in use at this
394 MakeCompositorFrame({child_id2})); 253 // time by virtue of being in the pending frame, so none can be returned to
395 254 // the client yet.
396 // parent_support is blocked on |child_id2|. 255 EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
397 EXPECT_TRUE(dependency_tracker().has_deadline()); 256 fake_support_client_.clear_returned_resources();
398 EXPECT_FALSE(parent_surface()->HasActiveFrame()); 257
399 EXPECT_TRUE(parent_surface()->HasPendingFrame()); 258 // Hold on to everything.
400 EXPECT_THAT(parent_surface()->blocking_surfaces(), 259 RefCurrentFrameResources();
401 UnorderedElementsAre(child_id2)); 260
402 261 // The second frame references no resources and thus should make all resources
403 // child_support1 should now be blocked on |child_id2|. 262 // available to be returned as soon as the resource provider releases them.
404 child_support1().SubmitCompositorFrame(child_id1.local_surface_id(), 263 SubmitCompositorFrameWithResources(NULL, 0);
405 MakeCompositorFrame({child_id2})); 264
406 265 EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
407 EXPECT_TRUE(dependency_tracker().has_deadline()); 266 fake_support_client_.clear_returned_resources();
408 EXPECT_FALSE(child_surface1()->HasActiveFrame()); 267
409 EXPECT_TRUE(child_surface1()->HasPendingFrame()); 268 int release_counts[] = {1, 1, 1};
410 EXPECT_THAT(child_surface1()->blocking_surfaces(), 269 UnrefResources(first_frame_ids, release_counts, arraysize(first_frame_ids));
411 UnorderedElementsAre(child_id2)); 270
412 271 // None is returned to the client since DidReceiveCompositorAck is not
413 // The parent should still be blocked on |child_id2|. 272 // invoked.
414 EXPECT_THAT(parent_surface()->blocking_surfaces(), 273 EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
415 UnorderedElementsAre(child_id2)); 274
416 275 // Submitting an empty frame causes previous resources referenced by the
417 // Submit a CompositorFrame without any dependencies to |child_id2|. 276 // previous frame to be returned to client.
418 // parent_support should be activated. 277 SubmitCompositorFrameWithResources(nullptr, 0);
419 child_support2().SubmitCompositorFrame( 278 ResourceId expected_returned_ids[] = {1, 2, 3};
420 child_id2.local_surface_id(), MakeCompositorFrame(empty_surface_ids())); 279 int expected_returned_counts[] = {1, 1, 1};
421 280 CheckReturnedResourcesMatchExpected(
422 EXPECT_FALSE(dependency_tracker().has_deadline()); 281 expected_returned_ids, expected_returned_counts,
423 282 arraysize(expected_returned_counts), consumer_sync_token_);
424 // child_surface1 should now be active. 283 }
425 EXPECT_TRUE(child_surface1()->HasActiveFrame()); 284
426 EXPECT_FALSE(child_surface1()->HasPendingFrame()); 285 // Tests referencing a resource, unref'ing it to zero, then using it again
427 EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); 286 // before returning it to the client.
428 287 TEST_F(CompositorFrameSinkSupportTest, ResourceReusedBeforeReturn) {
429 // parent_surface should now be active. 288 ResourceId first_frame_ids[] = {7};
430 EXPECT_TRUE(parent_surface()->HasActiveFrame()); 289 SubmitCompositorFrameWithResources(first_frame_ids,
431 EXPECT_FALSE(parent_surface()->HasPendingFrame()); 290 arraysize(first_frame_ids));
432 EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); 291
433 } 292 // This removes all references to resource id 7.
434 293 SubmitCompositorFrameWithResources(NULL, 0);
435 // parent_surface is blocked on |child_id1|, and child_surface2 is blocked on 294
436 // |child_id2| until the deadline hits. 295 // This references id 7 again.
437 TEST_F(CompositorFrameSinkSupportTest, DisplayCompositorLockingDeadlineHits) { 296 SubmitCompositorFrameWithResources(first_frame_ids,
438 const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); 297 arraysize(first_frame_ids));
439 const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1); 298
440 const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1); 299 // This removes it again.
441 300 SubmitCompositorFrameWithResources(NULL, 0);
442 parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), 301
443 MakeCompositorFrame({child_id1})); 302 // Now it should be returned.
444 303 // We don't care how many entries are in the returned array for 7, so long as
445 // parent_support is blocked on |child_id1|. 304 // the total returned count matches the submitted count.
446 EXPECT_TRUE(dependency_tracker().has_deadline()); 305 const ReturnedResourceArray& returned =
447 EXPECT_FALSE(parent_surface()->HasActiveFrame()); 306 fake_support_client_.returned_resources();
448 EXPECT_TRUE(parent_surface()->HasPendingFrame()); 307 size_t return_count = 0;
449 EXPECT_THAT(parent_surface()->blocking_surfaces(), 308 for (size_t i = 0; i < returned.size(); ++i) {
450 UnorderedElementsAre(child_id1)); 309 EXPECT_EQ(7u, returned[i].id);
451 310 return_count += returned[i].count;
452 child_support1().SubmitCompositorFrame(child_id1.local_surface_id(), 311 }
453 MakeCompositorFrame({child_id2})); 312 EXPECT_EQ(2u, return_count);
454 313 }
455 // child_support1 should now be blocked on |child_id2|. 314
456 EXPECT_TRUE(dependency_tracker().has_deadline()); 315 // Tests having resources referenced multiple times, as if referenced by
457 EXPECT_FALSE(child_surface1()->HasActiveFrame()); 316 // multiple providers.
458 EXPECT_TRUE(child_surface1()->HasPendingFrame()); 317 TEST_F(CompositorFrameSinkSupportTest, ResourceRefMultipleTimes) {
459 EXPECT_THAT(child_surface1()->blocking_surfaces(), 318 ResourceId first_frame_ids[] = {3, 4};
460 UnorderedElementsAre(child_id2)); 319 SubmitCompositorFrameWithResources(first_frame_ids,
461 320 arraysize(first_frame_ids));
462 // The parent should still be blocked on |child_id1| because it's pending. 321
463 EXPECT_THAT(parent_surface()->blocking_surfaces(), 322 // Ref resources from the first frame twice.
464 UnorderedElementsAre(child_id1)); 323 RefCurrentFrameResources();
465 324 RefCurrentFrameResources();
466 BeginFrameArgs args = 325
467 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1); 326 ResourceId second_frame_ids[] = {4, 5};
468 327 SubmitCompositorFrameWithResources(second_frame_ids,
469 for (int i = 0; i < 3; ++i) { 328 arraysize(second_frame_ids));
470 begin_frame_source()->TestOnBeginFrame(args); 329
471 // There is still a looming deadline! Eeek! 330 // Ref resources from the second frame 3 times.
472 EXPECT_TRUE(dependency_tracker().has_deadline()); 331 RefCurrentFrameResources();
473 332 RefCurrentFrameResources();
474 // parent_support is still blocked on |child_id1|. 333 RefCurrentFrameResources();
475 EXPECT_FALSE(parent_surface()->HasActiveFrame()); 334
476 EXPECT_TRUE(parent_surface()->HasPendingFrame()); 335 // Submit a frame with no resources to remove all current frame refs from
477 EXPECT_THAT(parent_surface()->blocking_surfaces(), 336 // submitted resources.
478 UnorderedElementsAre(child_id1)); 337 SubmitCompositorFrameWithResources(NULL, 0);
479 338
480 // child_support1 is still blocked on |child_id2|. 339 EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
481 EXPECT_FALSE(child_surface1()->HasActiveFrame()); 340 fake_support_client_.clear_returned_resources();
482 EXPECT_TRUE(child_surface1()->HasPendingFrame()); 341
483 EXPECT_THAT(child_surface1()->blocking_surfaces(), 342 // Expected current refs:
484 UnorderedElementsAre(child_id2)); 343 // 3 -> 2
485 } 344 // 4 -> 2 + 3 = 5
486 345 // 5 -> 3
487 begin_frame_source()->TestOnBeginFrame(args); 346 {
488 347 SCOPED_TRACE("unref all 3");
489 // The deadline has passed. 348 ResourceId ids_to_unref[] = {3, 4, 5};
490 EXPECT_FALSE(dependency_tracker().has_deadline()); 349 int counts[] = {1, 1, 1};
491 350 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
492 // parent_surface has been activated. 351
493 EXPECT_TRUE(parent_surface()->HasActiveFrame()); 352 EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
494 EXPECT_FALSE(parent_surface()->HasPendingFrame()); 353 fake_support_client_.clear_returned_resources();
495 EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); 354
496 355 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
497 // child_surface1 has been activated. 356 SubmitCompositorFrameWithResources(nullptr, 0);
498 EXPECT_TRUE(child_surface1()->HasActiveFrame()); 357 ResourceId expected_returned_ids[] = {3};
499 EXPECT_FALSE(child_surface1()->HasPendingFrame()); 358 int expected_returned_counts[] = {1};
500 EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); 359 CheckReturnedResourcesMatchExpected(
501 } 360 expected_returned_ids, expected_returned_counts,
502 361 arraysize(expected_returned_counts), consumer_sync_token_);
503 // Verifies that the deadline does not reset if we submit CompositorFrames 362 }
504 // to new Surfaces with unresolved dependencies. 363
505 TEST_F(CompositorFrameSinkSupportTest, 364 // Expected refs remaining:
506 DisplayCompositorLockingFramesSubmittedAfterDeadlineSet) { 365 // 4 -> 3
507 const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1); 366 // 5 -> 1
508 BeginFrameArgs args = 367 {
509 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1); 368 SCOPED_TRACE("unref 4 and 5");
510 for (int i = 0; i < 3; ++i) { 369 ResourceId ids_to_unref[] = {4, 5};
511 LocalSurfaceId local_surface_id(1, base::UnguessableToken::Create()); 370 int counts[] = {1, 1};
512 support(i).SubmitCompositorFrame(local_surface_id, 371 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
513 MakeCompositorFrame({arbitrary_id})); 372 SubmitCompositorFrameWithResources(nullptr, 0);
514 // The deadline has been set. 373
515 EXPECT_TRUE(dependency_tracker().has_deadline()); 374 ResourceId expected_returned_ids[] = {5};
516 375 int expected_returned_counts[] = {1};
517 // support(i) should be blocked on arbitrary_id. 376 CheckReturnedResourcesMatchExpected(
518 EXPECT_FALSE(surface(i)->HasActiveFrame()); 377 expected_returned_ids, expected_returned_counts,
519 EXPECT_TRUE(surface(i)->HasPendingFrame()); 378 arraysize(expected_returned_counts), consumer_sync_token_);
520 EXPECT_THAT(surface(i)->blocking_surfaces(), 379 }
521 UnorderedElementsAre(arbitrary_id)); 380
522 381 // Now, just 2 refs remaining on resource 4. Unref both at once and make sure
523 // Issue a BeginFrame to get closer to the deadline. 382 // the returned count is correct.
524 begin_frame_source()->TestOnBeginFrame(args); 383 {
525 } 384 SCOPED_TRACE("unref only 4");
526 385 ResourceId ids_to_unref[] = {4};
527 // The deadline hits and all the Surfaces should activate. 386 int counts[] = {2};
528 begin_frame_source()->TestOnBeginFrame(args); 387 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
529 for (int i = 0; i < 3; ++i) { 388 SubmitCompositorFrameWithResources(nullptr, 0);
530 EXPECT_TRUE(surface(i)->HasActiveFrame()); 389
531 EXPECT_FALSE(surface(i)->HasPendingFrame()); 390 ResourceId expected_returned_ids[] = {4};
532 EXPECT_THAT(surface(i)->blocking_surfaces(), IsEmpty()); 391 int expected_returned_counts[] = {2};
533 } 392 CheckReturnedResourcesMatchExpected(
534 } 393 expected_returned_ids, expected_returned_counts,
535 394 arraysize(expected_returned_counts), consumer_sync_token_);
536 // This test verifies at the Surface activates once a CompositorFrame is 395 }
537 // submitted that has no unresolved dependencies. 396 }
538 TEST_F(CompositorFrameSinkSupportTest, 397
539 DisplayCompositorLockingNewFrameOverridesOldDependencies) { 398 TEST_F(CompositorFrameSinkSupportTest, ResourceLifetime) {
540 const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); 399 ResourceId first_frame_ids[] = {1, 2, 3};
541 const SurfaceId arbitrary_id = MakeSurfaceId(kArbitraryFrameSink, 1); 400 SubmitCompositorFrameWithResources(first_frame_ids,
542 401 arraysize(first_frame_ids));
543 // Submit a CompositorFrame that depends on |arbitrary_id|. 402
544 parent_support().SubmitCompositorFrame(parent_id.local_surface_id(), 403 // All of the resources submitted in the first frame are still in use at this
545 MakeCompositorFrame({arbitrary_id})); 404 // time by virtue of being in the pending frame, so none can be returned to
546 405 // the client yet.
547 // Verify that the CompositorFrame is blocked on |arbitrary_id|. 406 EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
548 EXPECT_FALSE(parent_surface()->HasActiveFrame()); 407 fake_support_client_.clear_returned_resources();
549 EXPECT_TRUE(parent_surface()->HasPendingFrame()); 408
550 EXPECT_THAT(parent_surface()->blocking_surfaces(), 409 // The second frame references some of the same resources, but some different
551 UnorderedElementsAre(arbitrary_id)); 410 // ones. We expect to receive back resource 1 with a count of 1 since it was
552 411 // only referenced by the first frame.
553 // Submit a CompositorFrame that has no dependencies. 412 ResourceId second_frame_ids[] = {2, 3, 4};
554 parent_support().SubmitCompositorFrame( 413 SubmitCompositorFrameWithResources(second_frame_ids,
555 parent_id.local_surface_id(), MakeCompositorFrame(empty_surface_ids())); 414 arraysize(second_frame_ids));
556 415 {
557 // Verify that the CompositorFrame has been activated. 416 SCOPED_TRACE("second frame");
558 EXPECT_TRUE(parent_surface()->HasActiveFrame()); 417 ResourceId expected_returned_ids[] = {1};
559 EXPECT_FALSE(parent_surface()->HasPendingFrame()); 418 int expected_returned_counts[] = {1};
560 EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); 419 CheckReturnedResourcesMatchExpected(
561 } 420 expected_returned_ids, expected_returned_counts,
562 421 arraysize(expected_returned_counts), gpu::SyncToken());
563 // This test verifies that a pending CompositorFrame does not affect surface 422 }
564 // references. A new surface from a child will continue to exist as a temporary 423
565 // reference until the parent's frame activates. 424 // The third frame references a disjoint set of resources, so we expect to
566 TEST_F(CompositorFrameSinkSupportTest, 425 // receive back all resources from the first and second frames. Resource IDs 2
567 OnlyActiveFramesAffectSurfaceReferences) { 426 // and 3 will have counts of 2, since they were used in both frames, and
568 const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); 427 // resource ID 4 will have a count of 1.
569 const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1); 428 ResourceId third_frame_ids[] = {10, 11, 12, 13};
570 const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1); 429 SubmitCompositorFrameWithResources(third_frame_ids,
571 430 arraysize(third_frame_ids));
572 // child_support1 submits a CompositorFrame without any dependencies. 431
573 // DidReceiveCompositorFrameAck should call on immediate activation. 432 {
574 EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(1); 433 SCOPED_TRACE("third frame");
575 child_support1().SubmitCompositorFrame(child_id1.local_surface_id(), 434 ResourceId expected_returned_ids[] = {2, 3, 4};
576 MakeCompositorFrame()); 435 int expected_returned_counts[] = {2, 2, 1};
577 testing::Mock::VerifyAndClearExpectations(&support_client_); 436 CheckReturnedResourcesMatchExpected(
578 437 expected_returned_ids, expected_returned_counts,
579 // Verify that the child surface is not blocked. 438 arraysize(expected_returned_counts), gpu::SyncToken());
580 EXPECT_TRUE(child_surface1()->HasActiveFrame()); 439 }
581 EXPECT_FALSE(child_surface1()->HasPendingFrame()); 440
582 EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); 441 // Simulate a ResourceProvider taking a ref on all of the resources.
583 442 RefCurrentFrameResources();
584 // Verify that there's a temporary reference for |child_id1|. 443
585 EXPECT_TRUE(HasTemporaryReference(child_id1)); 444 ResourceId fourth_frame_ids[] = {12, 13};
586 445 SubmitCompositorFrameWithResources(fourth_frame_ids,
587 // parent_support submits a CompositorFrame that depends on |child_id1| 446 arraysize(fourth_frame_ids));
588 // (which is already active) and |child_id2|. Thus, the parent should not 447
589 // activate immediately. DidReceiveCompositorFrameAck should not be called 448 EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
590 // immediately because the parent CompositorFrame is also blocked on 449
591 // |child_id2|. 450 RefCurrentFrameResources();
592 EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0); 451
593 parent_support().SubmitCompositorFrame( 452 // All resources are still being used by the external reference, so none can
594 parent_id.local_surface_id(), 453 // be returned to the client.
595 MakeCompositorFrame({child_id1, child_id2})); 454 EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
596 EXPECT_FALSE(parent_surface()->HasActiveFrame()); 455
597 EXPECT_TRUE(parent_surface()->HasPendingFrame()); 456 // Release resources associated with the first RefCurrentFrameResources() call
598 EXPECT_THAT(parent_surface()->blocking_surfaces(), 457 // first.
599 UnorderedElementsAre(child_id2)); 458 {
600 EXPECT_THAT(GetChildReferences(parent_id), IsEmpty()); 459 ResourceId ids_to_unref[] = {10, 11, 12, 13};
601 testing::Mock::VerifyAndClearExpectations(&support_client_); 460 int counts[] = {1, 1, 1, 1};
602 461 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
603 // Verify that there's a temporary reference for |child_id1| that still 462 }
604 // exists. 463
605 EXPECT_TRUE(HasTemporaryReference(child_id1)); 464 // Nothing is returned to the client yet since DidReceiveCompositorFrameAck
606 465 // is not invoked.
607 // child_support2 submits a CompositorFrame without any dependencies. 466 {
608 // Both the child and the parent should immediately ACK CompositorFrames 467 SCOPED_TRACE("fourth frame, first unref");
609 // on activation. 468 CheckReturnedResourcesMatchExpected(nullptr, nullptr, 0,
610 EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(2); 469 consumer_sync_token_);
611 child_support2().SubmitCompositorFrame(child_id2.local_surface_id(), 470 }
612 MakeCompositorFrame()); 471
613 testing::Mock::VerifyAndClearExpectations(&support_client_); 472 {
614 473 ResourceId ids_to_unref[] = {12, 13};
615 // Verify that the child surface is not blocked. 474 int counts[] = {1, 1};
616 EXPECT_TRUE(child_surface1()->HasActiveFrame()); 475 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
617 EXPECT_FALSE(child_surface1()->HasPendingFrame()); 476 }
618 EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); 477
619 478 // Resources 12 and 13 are still in use by the current frame, so they
620 // Verify that the parent surface's CompositorFrame has activated and that the 479 // shouldn't be available to be returned.
621 // temporary reference has been replaced by a permanent one. 480 EXPECT_EQ(0u, fake_support_client_.returned_resources().size());
622 EXPECT_TRUE(parent_surface()->HasActiveFrame()); 481
623 EXPECT_FALSE(parent_surface()->HasPendingFrame()); 482 // If we submit an empty frame, however, they should become available.
624 EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); 483 // Resources that were previously unref'd also return at this point.
625 EXPECT_FALSE(HasTemporaryReference(child_id1)); 484 SubmitCompositorFrameWithResources(NULL, 0u);
626 EXPECT_THAT(GetChildReferences(parent_id), 485
627 UnorderedElementsAre(child_id1, child_id2)); 486 {
628 } 487 SCOPED_TRACE("fourth frame, second unref");
629 488 ResourceId expected_returned_ids[] = {10, 11, 12, 13};
630 // This test verifies that we do not double count returned resources when a 489 int expected_returned_counts[] = {1, 1, 2, 2};
631 // CompositorFrame starts out as pending, then becomes active, and then is 490 CheckReturnedResourcesMatchExpected(
632 // replaced with another active CompositorFrame. 491 expected_returned_ids, expected_returned_counts,
633 TEST_F(CompositorFrameSinkSupportTest, 492 arraysize(expected_returned_counts), consumer_sync_token_);
634 DisplayCompositorLockingResourcesOnlyReturnedOnce) { 493 }
635 const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); 494 }
636 const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1); 495
637 496 TEST_F(CompositorFrameSinkSupportTest, AddDuringEviction) {
638 // The parent submits a CompositorFrame that depends on |child_id| before the 497 MockCompositorFrameSinkSupportClient mock_client;
639 // child submits a CompositorFrame. The CompositorFrame also has resources in 498 std::unique_ptr<CompositorFrameSinkSupport> support =
640 // its resource list. 499 CompositorFrameSinkSupport::Create(
641 TransferableResource resource = 500 &mock_client, &manager_, kAnotherArbitraryFrameSinkId, kIsRoot,
642 MakeResource(1337 /* id */, ALPHA_8 /* format */, 1234 /* filter */, 501 kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
643 gfx::Size(1234, 5678)); 502 LocalSurfaceId local_surface_id(6, kArbitraryToken);
644 TransferableResourceArray resource_list = {resource}; 503 support->SubmitCompositorFrame(local_surface_id, MakeCompositorFrame());
645 parent_support().SubmitCompositorFrame( 504
646 parent_id.local_surface_id(), 505 EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(_))
647 MakeCompositorFrameWithResources({child_id}, resource_list)); 506 .WillOnce(testing::InvokeWithoutArgs([&support, &mock_client]() {
648 507 LocalSurfaceId new_id(7, base::UnguessableToken::Create());
649 // Verify that the CompositorFrame is blocked on |child_id|. 508 support->SubmitCompositorFrame(new_id, MakeCompositorFrame());
650 EXPECT_FALSE(parent_surface()->HasActiveFrame()); 509 }))
651 EXPECT_TRUE(parent_surface()->HasPendingFrame()); 510 .WillRepeatedly(testing::Return());
652 EXPECT_THAT(parent_surface()->blocking_surfaces(), 511 support->EvictFrame();
653 UnorderedElementsAre(child_id)); 512 }
654 513
655 child_support1().SubmitCompositorFrame( 514 // Tests doing an EvictFrame before shutting down the factory.
656 child_id.local_surface_id(), MakeCompositorFrame(empty_surface_ids())); 515 TEST_F(CompositorFrameSinkSupportTest, EvictFrame) {
657 516 MockCompositorFrameSinkSupportClient mock_client;
658 // Verify that the child CompositorFrame activates immediately. 517 std::unique_ptr<CompositorFrameSinkSupport> support =
659 EXPECT_TRUE(child_surface1()->HasActiveFrame()); 518 CompositorFrameSinkSupport::Create(
660 EXPECT_FALSE(child_surface1()->HasPendingFrame()); 519 &mock_client, &manager_, kAnotherArbitraryFrameSinkId, kIsRoot,
661 EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty()); 520 kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
662 521 LocalSurfaceId local_surface_id(7, kArbitraryToken);
663 // Verify that the parent has activated. 522 SurfaceId id(kAnotherArbitraryFrameSinkId, local_surface_id);
664 EXPECT_TRUE(parent_surface()->HasActiveFrame()); 523
665 EXPECT_FALSE(parent_surface()->HasPendingFrame()); 524 TransferableResource resource;
666 EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty()); 525 resource.id = 1;
667 526 resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
668 // The parent submits a CompositorFrame without any dependencies. That frame
669 // should activate immediately, replacing the earlier frame. The resource from
670 // the earlier frame should be returned to the client.
671 parent_support().SubmitCompositorFrame(
672 parent_id.local_surface_id(), MakeCompositorFrame({empty_surface_ids()}));
673 EXPECT_TRUE(parent_surface()->HasActiveFrame());
674 EXPECT_FALSE(parent_surface()->HasPendingFrame());
675 EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
676 ReturnedResource returned_resource = resource.ToReturnedResource();
677 EXPECT_THAT(support_client_.last_returned_resources(),
678 UnorderedElementsAre(returned_resource));
679 }
680
681 // The parent Surface is blocked on |child_id2| which is blocked on |child_id3|.
682 // child_support1 evicts its blocked Surface. The parent surface should
683 // activate.
684 TEST_F(CompositorFrameSinkSupportTest, EvictSurfaceWithPendingFrame) {
685 const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
686 const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
687 const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
688
689 // Submit a CompositorFrame that depends on |child_id1|.
690 parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
691 MakeCompositorFrame({child_id1}));
692
693 // Verify that the CompositorFrame is blocked on |child_id1|.
694 EXPECT_FALSE(parent_surface()->HasActiveFrame());
695 EXPECT_TRUE(parent_surface()->HasPendingFrame());
696 EXPECT_THAT(parent_surface()->blocking_surfaces(),
697 UnorderedElementsAre(child_id1));
698
699 // Submit a CompositorFrame that depends on |child_id2|.
700 child_support1().SubmitCompositorFrame(child_id1.local_surface_id(),
701 MakeCompositorFrame({child_id2}));
702
703 // Verify that the CompositorFrame is blocked on |child_id2|.
704 EXPECT_FALSE(child_surface1()->HasActiveFrame());
705 EXPECT_TRUE(child_surface1()->HasPendingFrame());
706 EXPECT_THAT(child_surface1()->blocking_surfaces(),
707 UnorderedElementsAre(child_id2));
708
709 // Evict child_support1's current Surface.
710 // TODO(fsamuel): EvictFrame => EvictCurrentSurface.
711 child_support1().EvictFrame();
712
713 // The parent Surface should immediately activate.
714 EXPECT_TRUE(parent_surface()->HasActiveFrame());
715 EXPECT_FALSE(parent_surface()->HasPendingFrame());
716 EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
717 EXPECT_FALSE(dependency_tracker().has_deadline());
718 }
719
720 // This test verifies that if a surface has both a pending and active
721 // CompositorFrame and the pending CompositorFrame activates, replacing the
722 // existing active CompositorFrame, then the surface reference hierarchy will be
723 // updated allowing garbage collection of surfaces that are no longer
724 // referenced.
725 TEST_F(CompositorFrameSinkSupportTest, DropStaleReferencesAfterActivation) {
726 const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
727 const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
728 const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink2, 1);
729
730 // The parent submits a CompositorFrame that depends on |child_id1| before the
731 // child submits a CompositorFrame.
732 EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0);
733 parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
734 MakeCompositorFrame({child_id1}));
735
736 // Verify that the CompositorFrame is blocked on |child_id|.
737 EXPECT_FALSE(parent_surface()->HasActiveFrame());
738 EXPECT_TRUE(parent_surface()->HasPendingFrame());
739 EXPECT_THAT(parent_surface()->blocking_surfaces(),
740 UnorderedElementsAre(child_id1));
741 testing::Mock::VerifyAndClearExpectations(&support_client_);
742
743 // Verify that no references are added while the CompositorFrame is pending.
744 EXPECT_THAT(GetChildReferences(parent_id), IsEmpty());
745
746 // DidReceiveCompositorFrameAck should get called twice: once for the child
747 // and once for the now active parent CompositorFrame.
748 EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(2);
749 child_support1().SubmitCompositorFrame(
750 child_id1.local_surface_id(), MakeCompositorFrame(empty_surface_ids()));
751 testing::Mock::VerifyAndClearExpectations(&support_client_);
752
753 // Verify that the child CompositorFrame activates immediately.
754 EXPECT_TRUE(child_surface1()->HasActiveFrame());
755 EXPECT_FALSE(child_surface1()->HasPendingFrame());
756 EXPECT_THAT(child_surface1()->blocking_surfaces(), IsEmpty());
757
758 // Verify that the parent Surface has activated.
759 EXPECT_TRUE(parent_surface()->HasActiveFrame());
760 EXPECT_FALSE(parent_surface()->HasPendingFrame());
761 EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
762
763 // Verify that there is no temporary reference for the child and that
764 // the reference from the parent to the child still exists.
765 EXPECT_FALSE(HasTemporaryReference(child_id1));
766 EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1));
767
768 // The parent submits another CompositorFrame that depends on |child_id2|.
769 // Submitting a pending CompositorFrame will not trigger a CompositorFrameAck.
770 EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0);
771 parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
772 MakeCompositorFrame({child_id2}));
773 testing::Mock::VerifyAndClearExpectations(&support_client_);
774
775 // The parent surface should now have both a pending and activate
776 // CompositorFrame. Verify that the set of child references from
777 // |parent_id| are only from the active CompositorFrame.
778 EXPECT_TRUE(parent_surface()->HasActiveFrame());
779 EXPECT_TRUE(parent_surface()->HasPendingFrame());
780 EXPECT_THAT(parent_surface()->blocking_surfaces(),
781 UnorderedElementsAre(child_id2));
782 EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id1));
783
784 child_support2().SubmitCompositorFrame(
785 child_id2.local_surface_id(), MakeCompositorFrame(empty_surface_ids()));
786
787 // Verify that the parent Surface has activated and no longer has a pending
788 // CompositorFrame. Also verify that |child_id1| is no longer a child
789 // reference of |parent_id|.
790 EXPECT_TRUE(parent_surface()->HasActiveFrame());
791 EXPECT_FALSE(parent_surface()->HasPendingFrame());
792 EXPECT_THAT(parent_surface()->blocking_surfaces(), IsEmpty());
793 EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id2));
794 }
795
796 // Checks whether the latency info are moved to the new surface from the old
797 // one when LocalSurfaceId changes. No frame has unresolved dependencies.
798 TEST_F(CompositorFrameSinkSupportTest,
799 LatencyInfoCarriedOverOnResize_NoUnresolvedDependencies) {
800 const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
801 const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
802 const ui::LatencyComponentType latency_type1 =
803 ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
804 const int64_t latency_id1 = 234;
805 const int64_t latency_sequence_number1 = 5645432;
806 const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
807 const int64_t latency_id2 = 31434351;
808 const int64_t latency_sequence_number2 = 663788;
809
810 // Submit a frame with latency info
811 ui::LatencyInfo info;
812 info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
813
814 CompositorFrame frame = MakeCompositorFrame(); 527 CompositorFrame frame = MakeCompositorFrame();
815 frame.metadata.latency_info.push_back(info); 528 frame.resource_list.push_back(resource);
816 529 support->SubmitCompositorFrame(local_surface_id, std::move(frame));
817 parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(), 530 EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
818 std::move(frame)); 531 local_surface_id_ = LocalSurfaceId();
819 532
820 // Verify that the old surface has an active frame and no pending frame. 533 ReturnedResourceArray returned_resources = {resource.ToReturnedResource()};
821 Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1); 534 EXPECT_TRUE(manager_.GetSurfaceForId(id));
822 ASSERT_NE(nullptr, old_surface); 535 EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resources))
823 EXPECT_TRUE(old_surface->HasActiveFrame()); 536 .Times(1);
824 EXPECT_FALSE(old_surface->HasPendingFrame()); 537 support->EvictFrame();
825 538 EXPECT_FALSE(manager_.GetSurfaceForId(id));
826 // Submit another frame with some other latency info and a different 539 }
827 // LocalSurfaceId. 540
828 ui::LatencyInfo info2; 541 // Tests doing an EvictSurface which has unregistered dependency.
829 info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2); 542 TEST_F(CompositorFrameSinkSupportTest, EvictSurfaceDependencyUnRegistered) {
830 543 MockCompositorFrameSinkSupportClient mock_client;
831 CompositorFrame frame2 = MakeCompositorFrame(); 544 std::unique_ptr<CompositorFrameSinkSupport> support =
832 frame2.metadata.latency_info.push_back(info2); 545 CompositorFrameSinkSupport::Create(
833 546 &mock_client, &manager_, kAnotherArbitraryFrameSinkId, kIsRoot,
834 parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(), 547 kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
835 std::move(frame2)); 548 LocalSurfaceId local_surface_id(7, kArbitraryToken);
836 549
837 // Verify that the new surface has an active frame and no pending frames. 550 TransferableResource resource;
838 Surface* surface = surface_manager().GetSurfaceForId(parent_id2); 551 resource.id = 1;
839 ASSERT_NE(nullptr, surface); 552 resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
840 EXPECT_TRUE(surface->HasActiveFrame());
841 EXPECT_FALSE(surface->HasPendingFrame());
842
843 // Verify that the new surface has both latency info elements.
844 std::vector<ui::LatencyInfo> info_list;
845 surface->TakeLatencyInfo(&info_list);
846 EXPECT_EQ(2u, info_list.size());
847
848 ui::LatencyInfo aggregated_latency_info = info_list[0];
849 aggregated_latency_info.AddNewLatencyFrom(info_list[1]);
850
851 // Two components are the original ones, and the third one is
852 // DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, logged on compositor frame
853 // submit.
854 EXPECT_EQ(3u, aggregated_latency_info.latency_components().size());
855
856 ui::LatencyInfo::LatencyComponent comp1;
857 EXPECT_TRUE(
858 aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1));
859 EXPECT_EQ(latency_sequence_number1, comp1.sequence_number);
860 EXPECT_TRUE(
861 aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr));
862 EXPECT_TRUE(aggregated_latency_info.FindLatency(
863 ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, nullptr));
864 }
865
866 // Checks whether the latency info are moved to the new surface from the old
867 // one when LocalSurfaceId changes. Old surface has unresolved dependencies.
868 TEST_F(CompositorFrameSinkSupportTest,
869 LatencyInfoCarriedOverOnResize_OldSurfaceHasPendingAndActiveFrame) {
870 const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
871 const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
872 const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
873
874 const ui::LatencyComponentType latency_type1 =
875 ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
876 const int64_t latency_id1 = 234;
877 const int64_t latency_sequence_number1 = 5645432;
878 const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
879 const int64_t latency_id2 = 31434351;
880 const int64_t latency_sequence_number2 = 663788;
881
882 // Submit a frame with no unresolved dependecy.
883 ui::LatencyInfo info;
884 info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
885
886 CompositorFrame frame = MakeCompositorFrame(); 553 CompositorFrame frame = MakeCompositorFrame();
887 frame.metadata.latency_info.push_back(info); 554 frame.resource_list.push_back(resource);
888 555 support->SubmitCompositorFrame(local_surface_id, std::move(frame));
889 parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(), 556 EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
890 std::move(frame)); 557 local_surface_id_ = LocalSurfaceId();
891 558
892 // Submit a frame with unresolved dependencies. 559 SurfaceId surface_id(kAnotherArbitraryFrameSinkId, local_surface_id);
893 ui::LatencyInfo info2; 560 Surface* surface = manager_.GetSurfaceForId(surface_id);
894 info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2); 561 surface->AddDestructionDependency(
895 562 SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4));
896 CompositorFrame frame2 = MakeCompositorFrame({child_id}); 563
897 frame2.metadata.latency_info.push_back(info2); 564 ReturnedResourceArray returned_resource = {resource.ToReturnedResource()};
898 565
899 parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(), 566 EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
900 std::move(frame2)); 567 EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resource))
901 568 .Times(1);
902 // Verify that the old surface has both an active and a pending frame. 569 support->EvictFrame();
903 Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1); 570 EXPECT_FALSE(manager_.GetSurfaceForId(surface_id));
904 ASSERT_NE(nullptr, old_surface); 571 }
905 EXPECT_TRUE(old_surface->HasActiveFrame()); 572
906 EXPECT_TRUE(old_surface->HasPendingFrame()); 573 // Tests doing an EvictSurface which has registered dependency.
907 574 TEST_F(CompositorFrameSinkSupportTest, EvictSurfaceDependencyRegistered) {
908 // Submit a frame with a new local surface id. 575 MockCompositorFrameSinkSupportClient mock_client;
909 parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(), 576 std::unique_ptr<CompositorFrameSinkSupport> support =
910 MakeCompositorFrame()); 577 CompositorFrameSinkSupport::Create(
911 578 &mock_client, &manager_, kAnotherArbitraryFrameSinkId, kIsRoot,
912 // Verify that the new surface has an active frame only. 579 kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
913 Surface* surface = surface_manager().GetSurfaceForId(parent_id2); 580 LocalSurfaceId local_surface_id(7, kArbitraryToken);
914 ASSERT_NE(nullptr, surface); 581
915 EXPECT_TRUE(surface->HasActiveFrame()); 582 TransferableResource resource;
916 EXPECT_FALSE(surface->HasPendingFrame()); 583 resource.id = 1;
917 584 resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
918 // Verify that the new surface has latency info from both active and pending
919 // frame of the old surface.
920 std::vector<ui::LatencyInfo> info_list;
921 surface->TakeLatencyInfo(&info_list);
922 EXPECT_EQ(2u, info_list.size());
923
924 ui::LatencyInfo aggregated_latency_info = info_list[0];
925 aggregated_latency_info.AddNewLatencyFrom(info_list[1]);
926
927 // Two components are the original ones, and the third one is
928 // DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, logged on compositor frame
929 // submit.
930 EXPECT_EQ(3u, aggregated_latency_info.latency_components().size());
931
932 ui::LatencyInfo::LatencyComponent comp1;
933 EXPECT_TRUE(
934 aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1));
935 EXPECT_EQ(latency_sequence_number1, comp1.sequence_number);
936 EXPECT_TRUE(
937 aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr));
938 EXPECT_TRUE(aggregated_latency_info.FindLatency(
939 ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, nullptr));
940 }
941
942 // Checks whether the latency info are moved to the new surface from the old
943 // one when LocalSurfaceId changes. The new surface has unresolved dependencies.
944 TEST_F(CompositorFrameSinkSupportTest,
945 LatencyInfoCarriedOverOnResize_NewSurfaceHasPendingFrame) {
946 const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
947 const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
948 const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
949
950 const ui::LatencyComponentType latency_type1 =
951 ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
952 const int64_t latency_id1 = 234;
953 const int64_t latency_sequence_number1 = 5645432;
954 const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
955 const int64_t latency_id2 = 31434351;
956 const int64_t latency_sequence_number2 = 663788;
957
958 // Submit a frame with no unresolved dependencies.
959 ui::LatencyInfo info;
960 info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
961
962 CompositorFrame frame = MakeCompositorFrame(); 585 CompositorFrame frame = MakeCompositorFrame();
963 frame.metadata.latency_info.push_back(info); 586 frame.resource_list.push_back(resource);
964 587 uint32_t execute_count = 0;
965 parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(), 588 support->SubmitCompositorFrame(local_surface_id, std::move(frame));
966 std::move(frame)); 589 EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
967 590 local_surface_id_ = LocalSurfaceId();
968 // Verify that the old surface has an active frame only. 591
969 Surface* old_surface = surface_manager().GetSurfaceForId(parent_id1); 592 manager_.RegisterFrameSinkId(kYetAnotherArbitraryFrameSinkId);
970 ASSERT_NE(nullptr, old_surface); 593
971 EXPECT_TRUE(old_surface->HasActiveFrame()); 594 SurfaceId surface_id(kAnotherArbitraryFrameSinkId, local_surface_id);
972 EXPECT_FALSE(old_surface->HasPendingFrame()); 595 Surface* surface = manager_.GetSurfaceForId(surface_id);
973 596 surface->AddDestructionDependency(
974 // Submit a frame with a new local surface id and with unresolved 597 SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4));
975 // dependencies. 598
976 ui::LatencyInfo info2; 599 ReturnedResourceArray returned_resources;
977 info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2); 600 EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
978 601 support->EvictFrame();
979 CompositorFrame frame2 = MakeCompositorFrame({child_id}); 602 EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
980 frame2.metadata.latency_info.push_back(info2); 603 EXPECT_EQ(0u, execute_count);
981 604
982 parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(), 605 returned_resources.push_back(resource.ToReturnedResource());
983 std::move(frame2)); 606 EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resources))
984 607 .Times(1);
985 // Verify that the new surface has a pending frame and no active frame. 608 manager_.SatisfySequence(SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4));
986 Surface* surface = surface_manager().GetSurfaceForId(parent_id2); 609 EXPECT_FALSE(manager_.GetSurfaceForId(surface_id));
987 ASSERT_NE(nullptr, surface); 610 }
988 EXPECT_TRUE(surface->HasPendingFrame()); 611
989 EXPECT_FALSE(surface->HasActiveFrame()); 612 TEST_F(CompositorFrameSinkSupportTest, DestroySequence) {
990 613 LocalSurfaceId local_surface_id2(5, kArbitraryToken);
991 // Resolve the dependencies. The frame in parent's surface must become active. 614 std::unique_ptr<CompositorFrameSinkSupport> support2 =
992 child_support1().SubmitCompositorFrame(child_id.local_surface_id(), 615 CompositorFrameSinkSupport::Create(
993 MakeCompositorFrame()); 616 &fake_support_client_, &manager_, kYetAnotherArbitraryFrameSinkId,
994 EXPECT_FALSE(surface->HasPendingFrame()); 617 kIsChildRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
995 EXPECT_TRUE(surface->HasActiveFrame()); 618 SurfaceId id2(kYetAnotherArbitraryFrameSinkId, local_surface_id2);
996 619 support2->SubmitCompositorFrame(local_surface_id2, MakeCompositorFrame());
997 // Both latency info elements must exist in the now-activated frame of the 620
998 // new surface. 621 // Check that waiting before the sequence is satisfied works.
999 std::vector<ui::LatencyInfo> info_list; 622 manager_.GetSurfaceForId(id2)->AddDestructionDependency(
1000 surface->TakeLatencyInfo(&info_list); 623 SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4));
1001 EXPECT_EQ(2u, info_list.size()); 624 support2->EvictFrame();
1002 625
1003 ui::LatencyInfo aggregated_latency_info = info_list[0]; 626 DCHECK(manager_.GetSurfaceForId(id2));
1004 aggregated_latency_info.AddNewLatencyFrom(info_list[1]); 627 manager_.SatisfySequence(SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 4));
1005 628 manager_.SatisfySequence(SurfaceSequence(kYetAnotherArbitraryFrameSinkId, 6));
1006 // Two components are the original ones, and the third one is 629 DCHECK(!manager_.GetSurfaceForId(id2));
1007 // DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, logged on compositor frame 630
1008 // submit. 631 // Check that waiting after the sequence is satisfied works.
1009 EXPECT_EQ(3u, aggregated_latency_info.latency_components().size()); 632 support2->SubmitCompositorFrame(local_surface_id2, MakeCompositorFrame());
1010 633 DCHECK(manager_.GetSurfaceForId(id2));
1011 ui::LatencyInfo::LatencyComponent comp1; 634 manager_.GetSurfaceForId(id2)->AddDestructionDependency(
1012 EXPECT_TRUE( 635 SurfaceSequence(kAnotherArbitraryFrameSinkId, 6));
1013 aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1)); 636 support2->EvictFrame();
1014 EXPECT_EQ(latency_sequence_number1, comp1.sequence_number); 637 DCHECK(!manager_.GetSurfaceForId(id2));
1015 EXPECT_TRUE( 638 }
1016 aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr)); 639
1017 EXPECT_TRUE(aggregated_latency_info.FindLatency( 640 // Tests that Surface ID namespace invalidation correctly allows
1018 ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, nullptr)); 641 // Sequences to be ignored.
1019 } 642 TEST_F(CompositorFrameSinkSupportTest, InvalidFrameSinkId) {
1020 643 FrameSinkId frame_sink_id(1234, 5678);
1021 TEST_F(CompositorFrameSinkSupportTest, PassesOnBeginFrameAcks) { 644
1022 const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1); 645 LocalSurfaceId local_surface_id(5, kArbitraryToken);
1023 646 SurfaceId id(support_->frame_sink_id(), local_surface_id);
1024 // Request BeginFrames. 647 support_->SubmitCompositorFrame(local_surface_id, MakeCompositorFrame());
1025 display_support().SetNeedsBeginFrame(true); 648
1026 649 manager_.RegisterFrameSinkId(frame_sink_id);
1027 // Issue a BeginFrame. 650 manager_.GetSurfaceForId(id)->AddDestructionDependency(
1028 BeginFrameArgs args = 651 SurfaceSequence(frame_sink_id, 4));
1029 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1); 652
1030 begin_frame_source()->TestOnBeginFrame(args); 653 support_->EvictFrame();
1031 654
1032 // Check that the support forwards a BeginFrameDidNotSwap ack to the 655 // Verify the dependency has prevented the surface from getting destroyed.
1033 // BeginFrameSource. 656 EXPECT_TRUE(manager_.GetSurfaceForId(id));
1034 BeginFrameAck ack(0, 1, 1, false); 657
1035 display_support().BeginFrameDidNotSwap(ack); 658 manager_.InvalidateFrameSinkId(frame_sink_id);
1036 EXPECT_EQ(ack, begin_frame_source()->LastAckForObserver(&display_support())); 659
1037 660 // Verify that the invalidated namespace caused the unsatisfied sequence
1038 // Issue another BeginFrame. 661 // to be ignored.
1039 args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 2); 662 EXPECT_FALSE(manager_.GetSurfaceForId(id));
1040 begin_frame_source()->TestOnBeginFrame(args); 663 }
1041 664
1042 // Check that the support forwards the BeginFrameAck attached 665 TEST_F(CompositorFrameSinkSupportTest, DestroyCycle) {
1043 // to a CompositorFrame to the BeginFrameSource. 666 LocalSurfaceId local_surface_id2(5, kArbitraryToken);
1044 BeginFrameAck ack2(0, 2, 2, true); 667 SurfaceId id2(kYetAnotherArbitraryFrameSinkId, local_surface_id2);
668 std::unique_ptr<CompositorFrameSinkSupport> support2 =
669 CompositorFrameSinkSupport::Create(
670 &fake_support_client_, &manager_, kYetAnotherArbitraryFrameSinkId,
671 kIsChildRoot, kHandlesFrameSinkIdInvalidation, kNeedsSyncPoints);
672 manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId);
673 // Give id2 a frame that references local_surface_id_.
674 {
675 std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
676 CompositorFrame frame = MakeCompositorFrame();
677 frame.render_pass_list.push_back(std::move(render_pass));
678 frame.metadata.referenced_surfaces.push_back(
679 SurfaceId(support_->frame_sink_id(), local_surface_id_));
680 support2->SubmitCompositorFrame(local_surface_id2, std::move(frame));
681 EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id2);
682 }
683 manager_.GetSurfaceForId(id2)->AddDestructionDependency(
684 SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
685 support2->EvictFrame();
686 // Give local_surface_id_ a frame that references id2.
687 {
688 std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
689 CompositorFrame frame = MakeCompositorFrame();
690 frame.render_pass_list.push_back(std::move(render_pass));
691 frame.metadata.referenced_surfaces.push_back(id2);
692 support_->SubmitCompositorFrame(local_surface_id_, std::move(frame));
693 }
694 support_->EvictFrame();
695 EXPECT_TRUE(manager_.GetSurfaceForId(id2));
696 // local_surface_id_ should be retained by reference from id2.
697 EXPECT_TRUE(manager_.GetSurfaceForId(
698 SurfaceId(support_->frame_sink_id(), local_surface_id_)));
699
700 // Satisfy last destruction dependency for id2.
701 manager_.SatisfySequence(SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
702
703 // id2 and local_surface_id_ are in a reference cycle that has no surface
704 // sequences holding on to it, so they should be destroyed.
705 EXPECT_TRUE(!manager_.GetSurfaceForId(id2));
706 EXPECT_TRUE(!manager_.GetSurfaceForId(
707 SurfaceId(support_->frame_sink_id(), local_surface_id_)));
708
709 local_surface_id_ = LocalSurfaceId();
710 }
711
712 void CopyRequestTestCallback(bool* called,
713 std::unique_ptr<CopyOutputResult> result) {
714 *called = true;
715 }
716
717 TEST_F(CompositorFrameSinkSupportTest, DuplicateCopyRequest) {
718 {
719 std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
720 CompositorFrame frame = MakeCompositorFrame();
721 frame.render_pass_list.push_back(std::move(render_pass));
722 frame.metadata.referenced_surfaces.push_back(
723 SurfaceId(support_->frame_sink_id(), local_surface_id_));
724 support_->SubmitCompositorFrame(local_surface_id_, std::move(frame));
725 EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id_);
726 }
727
728 bool called1 = false;
729 std::unique_ptr<CopyOutputRequest> request;
730 request = CopyOutputRequest::CreateRequest(
731 base::Bind(&CopyRequestTestCallback, &called1));
732 request->set_source(kArbitrarySourceId1);
733
734 support_->RequestCopyOfSurface(std::move(request));
735 EXPECT_FALSE(called1);
736
737 bool called2 = false;
738 request = CopyOutputRequest::CreateRequest(
739 base::Bind(&CopyRequestTestCallback, &called2));
740 request->set_source(kArbitrarySourceId2);
741
742 support_->RequestCopyOfSurface(std::move(request));
743 // Callbacks have different sources so neither should be called.
744 EXPECT_FALSE(called1);
745 EXPECT_FALSE(called2);
746
747 bool called3 = false;
748 request = CopyOutputRequest::CreateRequest(
749 base::Bind(&CopyRequestTestCallback, &called3));
750 request->set_source(kArbitrarySourceId1);
751
752 support_->RequestCopyOfSurface(std::move(request));
753 // Two callbacks are from source1, so the first should be called.
754 EXPECT_TRUE(called1);
755 EXPECT_FALSE(called2);
756 EXPECT_FALSE(called3);
757
758 support_->EvictFrame();
759 local_surface_id_ = LocalSurfaceId();
760 EXPECT_TRUE(called1);
761 EXPECT_TRUE(called2);
762 EXPECT_TRUE(called3);
763 }
764
765 // Check whether the SurfaceInfo object is created and populated correctly
766 // after the frame submission.
767 TEST_F(CompositorFrameSinkSupportTest, SurfaceInfo) {
1045 CompositorFrame frame = MakeCompositorFrame(); 768 CompositorFrame frame = MakeCompositorFrame();
1046 frame.metadata.begin_frame_ack = ack2; 769
1047 display_support().SubmitCompositorFrame(display_id.local_surface_id(), 770 auto render_pass = RenderPass::Create();
1048 std::move(frame)); 771 render_pass->SetNew(1, gfx::Rect(5, 6), gfx::Rect(), gfx::Transform());
1049 EXPECT_EQ(ack2, begin_frame_source()->LastAckForObserver(&display_support())); 772 frame.render_pass_list.push_back(std::move(render_pass));
1050 } 773
1051 774 render_pass = RenderPass::Create();
1052 // Checks that resources and ack are sent together if possible. 775 render_pass->SetNew(2, gfx::Rect(7, 8), gfx::Rect(), gfx::Transform());
1053 TEST_F(CompositorFrameSinkSupportTest, ReturnResourcesWithAck) { 776 frame.render_pass_list.push_back(std::move(render_pass));
1054 const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); 777
1055 TransferableResource resource; 778 frame.metadata.device_scale_factor = 2.5f;
1056 resource.id = 1234; 779
1057 parent_support().SubmitCompositorFrame( 780 support_->SubmitCompositorFrame(local_surface_id_, std::move(frame));
1058 parent_id.local_surface_id(), 781 SurfaceId expected_surface_id(support_->frame_sink_id(), local_surface_id_);
1059 MakeCompositorFrameWithResources(empty_surface_ids(), {resource})); 782 EXPECT_EQ(expected_surface_id, last_surface_info_.id());
1060 ReturnedResourceArray returned_resources; 783 EXPECT_EQ(2.5f, last_surface_info_.device_scale_factor());
1061 TransferableResource::ReturnResources({resource}, &returned_resources); 784 EXPECT_EQ(gfx::Size(7, 8), last_surface_info_.size_in_pixels());
1062 EXPECT_CALL(support_client_, ReclaimResources(_)).Times(0); 785 }
1063 EXPECT_CALL(support_client_, 786
1064 DidReceiveCompositorFrameAck(Eq(returned_resources))); 787 } // namespace test
1065 parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
1066 MakeCompositorFrame());
1067 }
1068
1069 // Verifies that if a surface is marked destroyed and a new frame arrives for
1070 // it, it will be recovered.
1071 TEST_F(CompositorFrameSinkSupportTest, SurfaceResurrection) {
1072 const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
1073 const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 3);
1074
1075 // Add a reference from the parent to the child.
1076 parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
1077 MakeCompositorFrame({child_id}));
1078
1079 // Create the child surface by submitting a frame to it.
1080 EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(child_id));
1081 child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
1082 MakeCompositorFrame());
1083
1084 // Verify that the child surface is created.
1085 Surface* surface = surface_manager().GetSurfaceForId(child_id);
1086 EXPECT_NE(nullptr, surface);
1087
1088 // Attempt to destroy the child surface. The surface must still exist since
1089 // the parent needs it but it will be marked as destroyed.
1090 child_support1().EvictFrame();
1091 surface = surface_manager().GetSurfaceForId(child_id);
1092 EXPECT_NE(nullptr, surface);
1093 EXPECT_TRUE(surface->destroyed());
1094
1095 // Child submits another frame to the same local surface id that is marked
1096 // destroyed.
1097 child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
1098 MakeCompositorFrame());
1099
1100 // Verify that the surface that was marked destroyed is recovered and is being
1101 // used again.
1102 Surface* surface2 = surface_manager().GetSurfaceForId(child_id);
1103 EXPECT_EQ(surface, surface2);
1104 EXPECT_FALSE(surface2->destroyed());
1105 }
1106
1107 // Verifies that if a LocalSurfaceId belonged to a surface that doesn't exist
1108 // anymore, it can still be reused for new surfaces.
1109 TEST_F(CompositorFrameSinkSupportTest, LocalSurfaceIdIsReusable) {
1110 const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
1111 const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 3);
1112
1113 // Add a reference from parent.
1114 parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
1115 MakeCompositorFrame({child_id}));
1116
1117 // Submit the first frame. Creates the surface.
1118 child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
1119 MakeCompositorFrame());
1120 EXPECT_NE(nullptr, surface_manager().GetSurfaceForId(child_id));
1121
1122 // Remove the reference from parant. This allows us to destroy the surface.
1123 parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
1124 MakeCompositorFrame());
1125
1126 // Destroy the surface.
1127 child_support1().EvictFrame();
1128 EXPECT_EQ(nullptr, surface_manager().GetSurfaceForId(child_id));
1129
1130 // Submit another frame with the same local surface id. This should work fine
1131 // and a new surface must be created.
1132 child_support1().SubmitCompositorFrame(child_id.local_surface_id(),
1133 MakeCompositorFrame());
1134 EXPECT_NE(nullptr, surface_manager().GetSurfaceForId(child_id));
1135 }
1136
1137 // This test verifies that a crash does not occur if garbage collection is
1138 // triggered during surface dependency resolution. This test triggers garbage
1139 // collection during surface resolution, by causing an activation to remove
1140 // a surface subtree from the root. Both the old subtree and the new
1141 // activated subtree refer to the same dependency. The old subtree was activated
1142 // by deadline, and the new subtree was activated by a dependency finally
1143 // resolving.
1144 TEST_F(CompositorFrameSinkSupportTest, DependencyTrackingGarbageCollection) {
1145 const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
1146 const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
1147 const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
1148 const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
1149
1150 parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
1151 MakeCompositorFrame({child_id}));
1152 display_support().SubmitCompositorFrame(display_id.local_surface_id(),
1153 MakeCompositorFrame({parent_id1}));
1154
1155 EXPECT_TRUE(dependency_tracker().has_deadline());
1156
1157 BeginFrameArgs args =
1158 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
1159
1160 // Advance BeginFrames to trigger a deadline.
1161 for (int i = 0; i < 3; ++i) {
1162 begin_frame_source()->TestOnBeginFrame(args);
1163 EXPECT_TRUE(dependency_tracker().has_deadline());
1164 }
1165 begin_frame_source()->TestOnBeginFrame(args);
1166 EXPECT_FALSE(dependency_tracker().has_deadline());
1167
1168 EXPECT_TRUE(display_surface()->HasActiveFrame());
1169 EXPECT_FALSE(display_surface()->HasPendingFrame());
1170 EXPECT_TRUE(parent_surface()->HasActiveFrame());
1171 EXPECT_FALSE(parent_surface()->HasPendingFrame());
1172
1173 parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(),
1174 MakeCompositorFrame({child_id}));
1175 display_support().SubmitCompositorFrame(display_id.local_surface_id(),
1176 MakeCompositorFrame({parent_id2}));
1177
1178 // The display surface now has two CompositorFrames. One that is pending,
1179 // indirectly blocked on child_id and one that is active, also indirectly
1180 // referring to child_id, but activated due to the deadline above.
1181 EXPECT_TRUE(display_surface()->HasActiveFrame());
1182 EXPECT_TRUE(display_surface()->HasPendingFrame());
1183
1184 // Submitting a CompositorFrame will trigger garbage collection of the
1185 // |parent_id1| subtree. This should not crash.
1186 child_support1().SubmitCompositorFrame(
1187 child_id.local_surface_id(), MakeCompositorFrame(empty_surface_ids()));
1188 }
1189
1190 // This test verifies that a crash does not occur if garbage collection is
1191 // triggered when a deadline forces frame activation. This test triggers garbage
1192 // collection during deadline activation by causing the activation of a display
1193 // frame to replace a previously activated display frame that was referring to
1194 // a now-unreachable surface subtree. That subtree gets garbage collected during
1195 // deadline activation. SurfaceDependencyTracker is also tracking a surface
1196 // from that subtree due to an unresolved dependency. This test verifies that
1197 // this dependency resolution does not crash.
1198 TEST_F(CompositorFrameSinkSupportTest, GarbageCollectionOnDeadline) {
1199 const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
1200 const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
1201 const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
1202 const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
1203
1204 display_support().SubmitCompositorFrame(display_id.local_surface_id(),
1205 MakeCompositorFrame({parent_id1}));
1206
1207 EXPECT_TRUE(display_surface()->HasPendingFrame());
1208 EXPECT_TRUE(dependency_tracker().has_deadline());
1209 EXPECT_FALSE(display_surface()->HasActiveFrame());
1210
1211 // Advance BeginFrames to trigger a deadline. This activates the
1212 // CompositorFrame submitted above.
1213 BeginFrameArgs args =
1214 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
1215 for (int i = 0; i < 3; ++i) {
1216 begin_frame_source()->TestOnBeginFrame(args);
1217 EXPECT_TRUE(dependency_tracker().has_deadline());
1218 }
1219 begin_frame_source()->TestOnBeginFrame(args);
1220 EXPECT_FALSE(dependency_tracker().has_deadline());
1221 EXPECT_FALSE(display_surface()->HasPendingFrame());
1222 EXPECT_TRUE(display_surface()->HasActiveFrame());
1223
1224 // |parent_id1| is blocked on |child_id|, but |display_id|'s CompositorFrame
1225 // has activated due to a deadline. |parent_id1| will be tracked by the
1226 // SurfaceDependencyTracker.
1227 parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
1228 MakeCompositorFrame({child_id}));
1229
1230 // By submitting a display CompositorFrame, and replacing the parent's
1231 // CompositorFrame with another surface ID, parent_id1 becomes unreachable and
1232 // a candidate for garbage collection.
1233 display_support().SubmitCompositorFrame(display_id.local_surface_id(),
1234 MakeCompositorFrame({parent_id2}));
1235
1236 // Now |parent_id1| is only kept alive by the active |display_id| frame.
1237 parent_support().SubmitCompositorFrame(parent_id2.local_surface_id(),
1238 MakeCompositorFrame({child_id}));
1239
1240 // SurfaceDependencyTracker should now be tracking |display_id|, |parent_id1|
1241 // and |parent_id2|. By activating the pending |display_id| frame by deadline,
1242 // |parent_id1| becomes unreachable and is garbage collected while
1243 // SurfaceDependencyTracker is in the process of activating surfaces. This
1244 // should not cause a crash or use-after-free.
1245 for (int i = 0; i < 3; ++i) {
1246 begin_frame_source()->TestOnBeginFrame(args);
1247 EXPECT_TRUE(dependency_tracker().has_deadline());
1248 }
1249 begin_frame_source()->TestOnBeginFrame(args);
1250 EXPECT_FALSE(dependency_tracker().has_deadline());
1251 }
1252
1253 // This test verifies that a CompositorFrame will only blocked on embedded
1254 // surfaces but not on other retained surface IDs in the CompositorFrame.
1255 TEST_F(CompositorFrameSinkSupportTest, OnlyBlockOnEmbeddedSurfaces) {
1256 const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
1257 const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
1258 const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
1259
1260 display_support().SubmitCompositorFrame(
1261 display_id.local_surface_id(),
1262 MakeCompositorFrame({parent_id1}, {parent_id1, parent_id2}));
1263
1264 EXPECT_TRUE(display_surface()->HasPendingFrame());
1265 EXPECT_FALSE(display_surface()->HasActiveFrame());
1266 EXPECT_TRUE(dependency_tracker().has_deadline());
1267
1268 // Verify that the display CompositorFrame will only block on |parent_id1| but
1269 // not |parent_id2|.
1270 EXPECT_THAT(display_surface()->blocking_surfaces(),
1271 UnorderedElementsAre(parent_id1));
1272 // Verify that the display surface holds no references while its
1273 // CompositorFrame is pending.
1274 EXPECT_THAT(GetChildReferences(display_id), IsEmpty());
1275
1276 // Submitting a CompositorFrame with |parent_id1| should unblock the display
1277 // CompositorFrame.
1278 parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
1279 MakeCompositorFrame());
1280
1281 EXPECT_FALSE(dependency_tracker().has_deadline());
1282 EXPECT_FALSE(display_surface()->HasPendingFrame());
1283 EXPECT_TRUE(display_surface()->HasActiveFrame());
1284 EXPECT_THAT(display_surface()->blocking_surfaces(), IsEmpty());
1285
1286 // Only a reference to |parent_id1| is added because |parent_id2| does not
1287 // exist.
1288 EXPECT_THAT(GetChildReferences(display_id), UnorderedElementsAre(parent_id1));
1289 }
1290
1291 // This test verifies that a late arriving CompositorFrame activates immediately
1292 // and does not trigger a new deadline.
1293 TEST_F(CompositorFrameSinkSupportTest, LateArrivingDependency) {
1294 const SurfaceId display_id = MakeSurfaceId(kDisplayFrameSink, 1);
1295 const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
1296 const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
1297
1298 display_support().SubmitCompositorFrame(display_id.local_surface_id(),
1299 MakeCompositorFrame({parent_id1}));
1300
1301 EXPECT_TRUE(display_surface()->HasPendingFrame());
1302 EXPECT_FALSE(display_surface()->HasActiveFrame());
1303 EXPECT_TRUE(dependency_tracker().has_deadline());
1304
1305 // Advance BeginFrames to trigger a deadline. This activates the
1306 // CompositorFrame submitted above.
1307 BeginFrameArgs args =
1308 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
1309 for (int i = 0; i < 3; ++i) {
1310 begin_frame_source()->TestOnBeginFrame(args);
1311 EXPECT_TRUE(dependency_tracker().has_deadline());
1312 }
1313 begin_frame_source()->TestOnBeginFrame(args);
1314 EXPECT_FALSE(dependency_tracker().has_deadline());
1315 EXPECT_FALSE(display_surface()->HasPendingFrame());
1316 EXPECT_TRUE(display_surface()->HasActiveFrame());
1317
1318 // A late arriving CompositorFrame should activate immediately without
1319 // scheduling a deadline and without waiting for dependencies to resolve.
1320 parent_support().SubmitCompositorFrame(parent_id1.local_surface_id(),
1321 MakeCompositorFrame({child_id1}));
1322 EXPECT_FALSE(dependency_tracker().has_deadline());
1323 EXPECT_FALSE(parent_surface()->HasPendingFrame());
1324 EXPECT_TRUE(parent_surface()->HasActiveFrame());
1325 }
1326 788
1327 } // namespace cc 789 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698