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

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

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

Powered by Google App Engine
This is Rietveld 408576698