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

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

Issue 2802023002: Remove SurfaceFactory And SurfaceFactoryClient (Closed)
Patch Set: Address Comments 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
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/surfaces/surface_factory.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <utility>
11 #include <vector>
12
13 #include "base/bind.h"
14 #include "base/macros.h"
15 #include "cc/output/compositor_frame.h"
16 #include "cc/output/copy_output_request.h"
17 #include "cc/output/copy_output_result.h"
18 #include "cc/resources/resource_provider.h"
19 #include "cc/surfaces/frame_sink_manager_client.h"
20 #include "cc/surfaces/surface.h"
21 #include "cc/surfaces/surface_factory_client.h"
22 #include "cc/surfaces/surface_info.h"
23 #include "cc/surfaces/surface_manager.h"
24 #include "cc/surfaces/surface_resource_holder_client.h"
25 #include "cc/test/fake_surface_resource_holder_client.h"
26 #include "cc/test/scheduler_test_common.h"
27 #include "cc/test/stub_surface_factory_client.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "ui/gfx/geometry/size.h"
30
31 namespace cc {
32 namespace {
33
34 static constexpr FrameSinkId kArbitraryFrameSinkId(1, 1);
35 static constexpr FrameSinkId kAnotherArbitraryFrameSinkId(2, 2);
36 static const base::UnguessableToken kArbitraryToken =
37 base::UnguessableToken::Create();
38 static auto kArbitrarySourceId1 =
39 base::UnguessableToken::Deserialize(0xdead, 0xbeef);
40 static auto kArbitrarySourceId2 =
41 base::UnguessableToken::Deserialize(0xdead, 0xbee0);
42
43 gpu::SyncToken GenTestSyncToken(int id) {
44 gpu::SyncToken token;
45 token.Set(gpu::CommandBufferNamespace::GPU_IO, 0,
46 gpu::CommandBufferId::FromUnsafeValue(id), 1);
47 return token;
48 }
49
50 class SurfaceFactoryTest : public testing::Test, public SurfaceObserver {
51 public:
52 SurfaceFactoryTest()
53 : factory_(new SurfaceFactory(kArbitraryFrameSinkId,
54 &manager_,
55 &stub_surface_factory_client_,
56 &fake_surface_resource_holder_client_)),
57 local_surface_id_(3, kArbitraryToken),
58 frame_sync_token_(GenTestSyncToken(4)),
59 consumer_sync_token_(GenTestSyncToken(5)) {
60 manager_.AddObserver(this);
61 }
62
63 const SurfaceId& last_created_surface_id() const {
64 return last_created_surface_id_;
65 }
66
67 // SurfaceObserver implementation.
68 void OnSurfaceCreated(const SurfaceInfo& surface_info) override {
69 EXPECT_EQ(kArbitraryFrameSinkId, surface_info.id().frame_sink_id());
70 last_created_surface_id_ = surface_info.id();
71 last_surface_info_ = surface_info;
72 }
73
74 void OnSurfaceDamaged(const SurfaceId& id, bool* changed) override {
75 *changed = true;
76 }
77
78 ~SurfaceFactoryTest() override {
79 manager_.RemoveObserver(this);
80 factory_->EvictSurface();
81 }
82
83 void SubmitCompositorFrameWithResources(ResourceId* resource_ids,
84 size_t num_resource_ids) {
85 CompositorFrame frame;
86 for (size_t i = 0u; i < num_resource_ids; ++i) {
87 TransferableResource resource;
88 resource.id = resource_ids[i];
89 resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
90 resource.mailbox_holder.sync_token = frame_sync_token_;
91 frame.resource_list.push_back(resource);
92 }
93 factory_->SubmitCompositorFrame(local_surface_id_, std::move(frame),
94 SurfaceFactory::DrawCallback(),
95 SurfaceFactory::WillDrawCallback());
96 EXPECT_EQ(last_created_surface_id_.local_surface_id(), local_surface_id_);
97 }
98
99 void UnrefResources(ResourceId* ids_to_unref,
100 int* counts_to_unref,
101 size_t num_ids_to_unref) {
102 ReturnedResourceArray unref_array;
103 for (size_t i = 0; i < num_ids_to_unref; ++i) {
104 ReturnedResource resource;
105 resource.sync_token = consumer_sync_token_;
106 resource.id = ids_to_unref[i];
107 resource.count = counts_to_unref[i];
108 unref_array.push_back(resource);
109 }
110 factory_->UnrefResources(unref_array);
111 }
112
113 void CheckReturnedResourcesMatchExpected(ResourceId* expected_returned_ids,
114 int* expected_returned_counts,
115 size_t expected_resources,
116 gpu::SyncToken expected_sync_token) {
117 const ReturnedResourceArray& actual_resources =
118 fake_surface_resource_holder_client_.returned_resources();
119 ASSERT_EQ(expected_resources, actual_resources.size());
120 for (size_t i = 0; i < expected_resources; ++i) {
121 ReturnedResource resource = actual_resources[i];
122 EXPECT_EQ(expected_sync_token, resource.sync_token);
123 EXPECT_EQ(expected_returned_ids[i], resource.id);
124 EXPECT_EQ(expected_returned_counts[i], resource.count);
125 }
126 fake_surface_resource_holder_client_.clear_returned_resources();
127 }
128
129 void RefCurrentFrameResources() {
130 Surface* surface = manager_.GetSurfaceForId(
131 SurfaceId(factory_->frame_sink_id(), local_surface_id_));
132 factory_->RefResources(surface->GetActiveFrame().resource_list);
133 }
134
135 protected:
136 SurfaceManager manager_;
137 StubSurfaceFactoryClient stub_surface_factory_client_;
138 FakeSurfaceResourceHolderClient fake_surface_resource_holder_client_;
139 std::unique_ptr<SurfaceFactory> factory_;
140 LocalSurfaceId local_surface_id_;
141 SurfaceId last_created_surface_id_;
142 SurfaceInfo last_surface_info_;
143
144 // This is the sync token submitted with the frame. It should never be
145 // returned to the client.
146 const gpu::SyncToken frame_sync_token_;
147
148 // This is the sync token returned by the consumer. It should always be
149 // returned to the client.
150 const gpu::SyncToken consumer_sync_token_;
151 };
152
153 // Tests submitting a frame with resources followed by one with no resources
154 // with no resource provider action in between.
155 TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) {
156 ResourceId first_frame_ids[] = {1, 2, 3};
157 SubmitCompositorFrameWithResources(first_frame_ids,
158 arraysize(first_frame_ids));
159
160 // All of the resources submitted in the first frame are still in use at this
161 // time by virtue of being in the pending frame, so none can be returned to
162 // the client yet.
163 EXPECT_EQ(0u,
164 fake_surface_resource_holder_client_.returned_resources().size());
165 fake_surface_resource_holder_client_.clear_returned_resources();
166
167 // The second frame references no resources of first frame and thus should
168 // make all resources of first frame available to be returned.
169 SubmitCompositorFrameWithResources(NULL, 0);
170
171 ResourceId expected_returned_ids[] = {1, 2, 3};
172 int expected_returned_counts[] = {1, 1, 1};
173 // Resources were never consumed so no sync token should be set.
174 CheckReturnedResourcesMatchExpected(
175 expected_returned_ids, expected_returned_counts,
176 arraysize(expected_returned_counts), gpu::SyncToken());
177
178 ResourceId third_frame_ids[] = {4, 5, 6};
179 SubmitCompositorFrameWithResources(third_frame_ids,
180 arraysize(third_frame_ids));
181
182 // All of the resources submitted in the third frame are still in use at this
183 // time by virtue of being in the pending frame, so none can be returned to
184 // the client yet.
185 EXPECT_EQ(0u,
186 fake_surface_resource_holder_client_.returned_resources().size());
187 fake_surface_resource_holder_client_.clear_returned_resources();
188
189 // The forth frame references no resources of third frame and thus should
190 // make all resources of third frame available to be returned.
191 ResourceId forth_frame_ids[] = {7, 8, 9};
192 SubmitCompositorFrameWithResources(forth_frame_ids,
193 arraysize(forth_frame_ids));
194
195 ResourceId forth_expected_returned_ids[] = {4, 5, 6};
196 int forth_expected_returned_counts[] = {1, 1, 1};
197 // Resources were never consumed so no sync token should be set.
198 CheckReturnedResourcesMatchExpected(
199 forth_expected_returned_ids, forth_expected_returned_counts,
200 arraysize(forth_expected_returned_counts), gpu::SyncToken());
201 }
202
203 // Tests submitting a frame with resources followed by one with no resources
204 // with the resource provider holding everything alive.
205 TEST_F(SurfaceFactoryTest, ResourceLifetimeSimpleWithProviderHoldingAlive) {
206 ResourceId first_frame_ids[] = {1, 2, 3};
207 SubmitCompositorFrameWithResources(first_frame_ids,
208 arraysize(first_frame_ids));
209
210 // All of the resources submitted in the first frame are still in use at this
211 // time by virtue of being in the pending frame, so none can be returned to
212 // the client yet.
213 EXPECT_EQ(0u,
214 fake_surface_resource_holder_client_.returned_resources().size());
215 fake_surface_resource_holder_client_.clear_returned_resources();
216
217 // Hold on to everything.
218 RefCurrentFrameResources();
219
220 // The second frame references no resources and thus should make all resources
221 // available to be returned as soon as the resource provider releases them.
222 SubmitCompositorFrameWithResources(NULL, 0);
223
224 EXPECT_EQ(0u,
225 fake_surface_resource_holder_client_.returned_resources().size());
226 fake_surface_resource_holder_client_.clear_returned_resources();
227
228 int release_counts[] = {1, 1, 1};
229 UnrefResources(first_frame_ids, release_counts, arraysize(first_frame_ids));
230
231 ResourceId expected_returned_ids[] = {1, 2, 3};
232 int expected_returned_counts[] = {1, 1, 1};
233 CheckReturnedResourcesMatchExpected(
234 expected_returned_ids, expected_returned_counts,
235 arraysize(expected_returned_counts), consumer_sync_token_);
236 }
237
238 // Tests referencing a resource, unref'ing it to zero, then using it again
239 // before returning it to the client.
240 TEST_F(SurfaceFactoryTest, ResourceReusedBeforeReturn) {
241 ResourceId first_frame_ids[] = {7};
242 SubmitCompositorFrameWithResources(first_frame_ids,
243 arraysize(first_frame_ids));
244
245 // This removes all references to resource id 7.
246 SubmitCompositorFrameWithResources(NULL, 0);
247
248 // This references id 7 again.
249 SubmitCompositorFrameWithResources(first_frame_ids,
250 arraysize(first_frame_ids));
251
252 // This removes it again.
253 SubmitCompositorFrameWithResources(NULL, 0);
254
255 // Now it should be returned.
256 // We don't care how many entries are in the returned array for 7, so long as
257 // the total returned count matches the submitted count.
258 const ReturnedResourceArray& returned =
259 fake_surface_resource_holder_client_.returned_resources();
260 size_t return_count = 0;
261 for (size_t i = 0; i < returned.size(); ++i) {
262 EXPECT_EQ(7u, returned[i].id);
263 return_count += returned[i].count;
264 }
265 EXPECT_EQ(2u, return_count);
266 }
267
268 // Tests having resources referenced multiple times, as if referenced by
269 // multiple providers.
270 TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) {
271 ResourceId first_frame_ids[] = {3, 4};
272 SubmitCompositorFrameWithResources(first_frame_ids,
273 arraysize(first_frame_ids));
274
275 // Ref resources from the first frame twice.
276 RefCurrentFrameResources();
277 RefCurrentFrameResources();
278
279 ResourceId second_frame_ids[] = {4, 5};
280 SubmitCompositorFrameWithResources(second_frame_ids,
281 arraysize(second_frame_ids));
282
283 // Ref resources from the second frame 3 times.
284 RefCurrentFrameResources();
285 RefCurrentFrameResources();
286 RefCurrentFrameResources();
287
288 // Submit a frame with no resources to remove all current frame refs from
289 // submitted resources.
290 SubmitCompositorFrameWithResources(NULL, 0);
291
292 EXPECT_EQ(0u,
293 fake_surface_resource_holder_client_.returned_resources().size());
294 fake_surface_resource_holder_client_.clear_returned_resources();
295
296 // Expected current refs:
297 // 3 -> 2
298 // 4 -> 2 + 3 = 5
299 // 5 -> 3
300 {
301 SCOPED_TRACE("unref all 3");
302 ResourceId ids_to_unref[] = {3, 4, 5};
303 int counts[] = {1, 1, 1};
304 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
305
306 EXPECT_EQ(0u,
307 fake_surface_resource_holder_client_.returned_resources().size());
308 fake_surface_resource_holder_client_.clear_returned_resources();
309
310 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
311
312 ResourceId expected_returned_ids[] = {3};
313 int expected_returned_counts[] = {1};
314 CheckReturnedResourcesMatchExpected(
315 expected_returned_ids, expected_returned_counts,
316 arraysize(expected_returned_counts), consumer_sync_token_);
317 }
318
319 // Expected refs remaining:
320 // 4 -> 3
321 // 5 -> 1
322 {
323 SCOPED_TRACE("unref 4 and 5");
324 ResourceId ids_to_unref[] = {4, 5};
325 int counts[] = {1, 1};
326 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
327
328 ResourceId expected_returned_ids[] = {5};
329 int expected_returned_counts[] = {1};
330 CheckReturnedResourcesMatchExpected(
331 expected_returned_ids, expected_returned_counts,
332 arraysize(expected_returned_counts), consumer_sync_token_);
333 }
334
335 // Now, just 2 refs remaining on resource 4. Unref both at once and make sure
336 // the returned count is correct.
337 {
338 SCOPED_TRACE("unref only 4");
339 ResourceId ids_to_unref[] = {4};
340 int counts[] = {2};
341 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
342
343 ResourceId expected_returned_ids[] = {4};
344 int expected_returned_counts[] = {2};
345 CheckReturnedResourcesMatchExpected(
346 expected_returned_ids, expected_returned_counts,
347 arraysize(expected_returned_counts), consumer_sync_token_);
348 }
349 }
350
351 TEST_F(SurfaceFactoryTest, ResourceLifetime) {
352 ResourceId first_frame_ids[] = {1, 2, 3};
353 SubmitCompositorFrameWithResources(first_frame_ids,
354 arraysize(first_frame_ids));
355
356 // All of the resources submitted in the first frame are still in use at this
357 // time by virtue of being in the pending frame, so none can be returned to
358 // the client yet.
359 EXPECT_EQ(0u,
360 fake_surface_resource_holder_client_.returned_resources().size());
361 fake_surface_resource_holder_client_.clear_returned_resources();
362
363 // The second frame references some of the same resources, but some different
364 // ones. We expect to receive back resource 1 with a count of 1 since it was
365 // only referenced by the first frame.
366 ResourceId second_frame_ids[] = {2, 3, 4};
367 SubmitCompositorFrameWithResources(second_frame_ids,
368 arraysize(second_frame_ids));
369
370 {
371 SCOPED_TRACE("second frame");
372 ResourceId expected_returned_ids[] = {1};
373 int expected_returned_counts[] = {1};
374 CheckReturnedResourcesMatchExpected(
375 expected_returned_ids, expected_returned_counts,
376 arraysize(expected_returned_counts), gpu::SyncToken());
377 }
378
379 // The third frame references a disjoint set of resources, so we expect to
380 // receive back all resources from the first and second frames. Resource IDs 2
381 // and 3 will have counts of 2, since they were used in both frames, and
382 // resource ID 4 will have a count of 1.
383 ResourceId third_frame_ids[] = {10, 11, 12, 13};
384 SubmitCompositorFrameWithResources(third_frame_ids,
385 arraysize(third_frame_ids));
386
387 {
388 SCOPED_TRACE("third frame");
389 ResourceId expected_returned_ids[] = {2, 3, 4};
390 int expected_returned_counts[] = {2, 2, 1};
391 CheckReturnedResourcesMatchExpected(
392 expected_returned_ids, expected_returned_counts,
393 arraysize(expected_returned_counts), gpu::SyncToken());
394 }
395
396 // Simulate a ResourceProvider taking a ref on all of the resources.
397 RefCurrentFrameResources();
398
399 ResourceId fourth_frame_ids[] = {12, 13};
400 SubmitCompositorFrameWithResources(fourth_frame_ids,
401 arraysize(fourth_frame_ids));
402
403 EXPECT_EQ(0u,
404 fake_surface_resource_holder_client_.returned_resources().size());
405
406 RefCurrentFrameResources();
407
408 // All resources are still being used by the external reference, so none can
409 // be returned to the client.
410 EXPECT_EQ(0u,
411 fake_surface_resource_holder_client_.returned_resources().size());
412
413 // Release resources associated with the first RefCurrentFrameResources() call
414 // first.
415 {
416 ResourceId ids_to_unref[] = {10, 11, 12, 13};
417 int counts[] = {1, 1, 1, 1};
418 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
419 }
420
421 {
422 SCOPED_TRACE("fourth frame, first unref");
423 ResourceId expected_returned_ids[] = {10, 11};
424 int expected_returned_counts[] = {1, 1};
425 CheckReturnedResourcesMatchExpected(
426 expected_returned_ids, expected_returned_counts,
427 arraysize(expected_returned_counts), consumer_sync_token_);
428 }
429
430 {
431 ResourceId ids_to_unref[] = {12, 13};
432 int counts[] = {1, 1};
433 UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
434 }
435
436 // Resources 12 and 13 are still in use by the current frame, so they
437 // shouldn't be available to be returned.
438 EXPECT_EQ(0u,
439 fake_surface_resource_holder_client_.returned_resources().size());
440
441 // If we submit an empty frame, however, they should become available.
442 SubmitCompositorFrameWithResources(NULL, 0u);
443
444 {
445 SCOPED_TRACE("fourth frame, second unref");
446 ResourceId expected_returned_ids[] = {12, 13};
447 int expected_returned_counts[] = {2, 2};
448 CheckReturnedResourcesMatchExpected(
449 expected_returned_ids, expected_returned_counts,
450 arraysize(expected_returned_counts), consumer_sync_token_);
451 }
452 }
453
454 TEST_F(SurfaceFactoryTest, BlankNoIndexIncrement) {
455 LocalSurfaceId local_surface_id(6, kArbitraryToken);
456 SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id);
457 factory_->SubmitCompositorFrame(local_surface_id, CompositorFrame(),
458 SurfaceFactory::DrawCallback(),
459 SurfaceFactory::WillDrawCallback());
460 Surface* surface = manager_.GetSurfaceForId(surface_id);
461 ASSERT_NE(nullptr, surface);
462 EXPECT_EQ(2, surface->frame_index());
463 EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
464 }
465
466 void CreateSurfaceDrawCallback(SurfaceFactory* factory,
467 uint32_t* execute_count) {
468 LocalSurfaceId new_id(7, base::UnguessableToken::Create());
469 factory->SubmitCompositorFrame(new_id, CompositorFrame(),
470 SurfaceFactory::DrawCallback(),
471 SurfaceFactory::WillDrawCallback());
472 factory->EvictSurface();
473 *execute_count += 1;
474 }
475
476 TEST_F(SurfaceFactoryTest, AddDuringEviction) {
477 LocalSurfaceId local_surface_id(6, kArbitraryToken);
478
479 uint32_t execute_count = 0;
480 factory_->SubmitCompositorFrame(
481 local_surface_id, CompositorFrame(),
482 base::Bind(&CreateSurfaceDrawCallback, base::Unretained(factory_.get()),
483 &execute_count),
484 SurfaceFactory::WillDrawCallback());
485 EXPECT_EQ(0u, execute_count);
486 factory_->EvictSurface();
487 EXPECT_EQ(1u, execute_count);
488 }
489
490 void DrawCallback(uint32_t* execute_count) {
491 *execute_count += 1;
492 }
493
494 // Tests doing an EvictSurface before shutting down the factory.
495 TEST_F(SurfaceFactoryTest, EvictSurface) {
496 LocalSurfaceId local_surface_id(7, kArbitraryToken);
497 SurfaceId id(kArbitraryFrameSinkId, local_surface_id);
498
499 TransferableResource resource;
500 resource.id = 1;
501 resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
502 CompositorFrame frame;
503 frame.resource_list.push_back(resource);
504 uint32_t execute_count = 0;
505 factory_->SubmitCompositorFrame(local_surface_id, std::move(frame),
506 base::Bind(&DrawCallback, &execute_count),
507 SurfaceFactory::WillDrawCallback());
508 EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
509 local_surface_id_ = LocalSurfaceId();
510
511 EXPECT_TRUE(manager_.GetSurfaceForId(id));
512 EXPECT_TRUE(
513 fake_surface_resource_holder_client_.returned_resources().empty());
514 factory_->EvictSurface();
515 EXPECT_FALSE(manager_.GetSurfaceForId(id));
516 EXPECT_FALSE(
517 fake_surface_resource_holder_client_.returned_resources().empty());
518 EXPECT_EQ(1u, execute_count);
519 }
520
521 // Tests doing an EvictSurface which has unregistered dependency.
522 TEST_F(SurfaceFactoryTest, EvictSurfaceDependencyUnRegistered) {
523 LocalSurfaceId local_surface_id(7, kArbitraryToken);
524
525 TransferableResource resource;
526 resource.id = 1;
527 resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
528 CompositorFrame frame;
529 frame.resource_list.push_back(resource);
530 uint32_t execute_count = 0;
531 factory_->SubmitCompositorFrame(local_surface_id, std::move(frame),
532 base::Bind(&DrawCallback, &execute_count),
533 SurfaceFactory::WillDrawCallback());
534 EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
535 local_surface_id_ = LocalSurfaceId();
536
537 SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id);
538 Surface* surface = manager_.GetSurfaceForId(surface_id);
539 surface->AddDestructionDependency(
540 SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
541
542 EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
543 EXPECT_TRUE(
544 fake_surface_resource_holder_client_.returned_resources().empty());
545 factory_->EvictSurface();
546 EXPECT_FALSE(manager_.GetSurfaceForId(surface_id));
547 EXPECT_FALSE(
548 fake_surface_resource_holder_client_.returned_resources().empty());
549 EXPECT_EQ(1u, execute_count);
550 }
551
552 // Tests doing an EvictSurface which has registered dependency.
553 TEST_F(SurfaceFactoryTest, EvictSurfaceDependencyRegistered) {
554 LocalSurfaceId local_surface_id(7, kArbitraryToken);
555
556 TransferableResource resource;
557 resource.id = 1;
558 resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
559 CompositorFrame frame;
560 frame.resource_list.push_back(resource);
561 uint32_t execute_count = 0;
562 factory_->SubmitCompositorFrame(local_surface_id, std::move(frame),
563 base::Bind(&DrawCallback, &execute_count),
564 SurfaceFactory::WillDrawCallback());
565 EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id);
566 local_surface_id_ = LocalSurfaceId();
567
568 manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId);
569
570 SurfaceId surface_id(kArbitraryFrameSinkId, local_surface_id);
571 Surface* surface = manager_.GetSurfaceForId(surface_id);
572 surface->AddDestructionDependency(
573 SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
574
575 EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
576 EXPECT_TRUE(
577 fake_surface_resource_holder_client_.returned_resources().empty());
578 factory_->EvictSurface();
579 EXPECT_TRUE(manager_.GetSurfaceForId(surface_id));
580 EXPECT_TRUE(
581 fake_surface_resource_holder_client_.returned_resources().empty());
582 EXPECT_EQ(0u, execute_count);
583
584 manager_.SatisfySequence(SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
585 EXPECT_FALSE(manager_.GetSurfaceForId(surface_id));
586 EXPECT_FALSE(
587 fake_surface_resource_holder_client_.returned_resources().empty());
588 }
589
590 TEST_F(SurfaceFactoryTest, DestroySequence) {
591 LocalSurfaceId local_surface_id2(5, kArbitraryToken);
592 std::unique_ptr<SurfaceFactory> factory2(new SurfaceFactory(
593 kArbitraryFrameSinkId, &manager_, &stub_surface_factory_client_,
594 &fake_surface_resource_holder_client_));
595 SurfaceId id2(kArbitraryFrameSinkId, local_surface_id2);
596 factory2->SubmitCompositorFrame(local_surface_id2, CompositorFrame(),
597 SurfaceFactory::DrawCallback(),
598 SurfaceFactory::WillDrawCallback());
599
600 manager_.RegisterFrameSinkId(kArbitraryFrameSinkId);
601
602 // Check that waiting before the sequence is satisfied works.
603 manager_.GetSurfaceForId(id2)->AddDestructionDependency(
604 SurfaceSequence(kArbitraryFrameSinkId, 4));
605 factory2->EvictSurface();
606
607 DCHECK(manager_.GetSurfaceForId(id2));
608 manager_.SatisfySequence(SurfaceSequence(kArbitraryFrameSinkId, 4));
609 manager_.SatisfySequence(SurfaceSequence(kArbitraryFrameSinkId, 6));
610 DCHECK(!manager_.GetSurfaceForId(id2));
611
612 // Check that waiting after the sequence is satisfied works.
613 factory2->SubmitCompositorFrame(local_surface_id2, CompositorFrame(),
614 SurfaceFactory::DrawCallback(),
615 SurfaceFactory::WillDrawCallback());
616 DCHECK(manager_.GetSurfaceForId(id2));
617 manager_.GetSurfaceForId(id2)->AddDestructionDependency(
618 SurfaceSequence(kAnotherArbitraryFrameSinkId, 6));
619 factory2->EvictSurface();
620 DCHECK(!manager_.GetSurfaceForId(id2));
621 }
622
623 // Tests that Surface ID namespace invalidation correctly allows
624 // Sequences to be ignored.
625 TEST_F(SurfaceFactoryTest, InvalidFrameSinkId) {
626 FrameSinkId frame_sink_id(1234, 5678);
627
628 LocalSurfaceId local_surface_id(5, kArbitraryToken);
629 SurfaceId id(factory_->frame_sink_id(), local_surface_id);
630 factory_->SubmitCompositorFrame(local_surface_id, CompositorFrame(),
631 SurfaceFactory::DrawCallback(),
632 SurfaceFactory::WillDrawCallback());
633
634 manager_.RegisterFrameSinkId(frame_sink_id);
635 manager_.GetSurfaceForId(id)->AddDestructionDependency(
636 SurfaceSequence(frame_sink_id, 4));
637
638 factory_->EvictSurface();
639
640 // Verify the dependency has prevented the surface from getting destroyed.
641 EXPECT_TRUE(manager_.GetSurfaceForId(id));
642
643 manager_.InvalidateFrameSinkId(frame_sink_id);
644
645 // Verify that the invalidated namespace caused the unsatisfied sequence
646 // to be ignored.
647 EXPECT_FALSE(manager_.GetSurfaceForId(id));
648 }
649
650 TEST_F(SurfaceFactoryTest, DestroyCycle) {
651 LocalSurfaceId local_surface_id2(5, kArbitraryToken);
652 SurfaceId id2(kArbitraryFrameSinkId, local_surface_id2);
653 std::unique_ptr<SurfaceFactory> factory2(new SurfaceFactory(
654 kArbitraryFrameSinkId, &manager_, &stub_surface_factory_client_,
655 &fake_surface_resource_holder_client_));
656 manager_.RegisterFrameSinkId(kAnotherArbitraryFrameSinkId);
657 // Give id2 a frame that references local_surface_id_.
658 {
659 std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
660 CompositorFrame frame;
661 frame.render_pass_list.push_back(std::move(render_pass));
662 frame.metadata.referenced_surfaces.push_back(
663 SurfaceId(factory_->frame_sink_id(), local_surface_id_));
664 factory2->SubmitCompositorFrame(local_surface_id2, std::move(frame),
665 SurfaceFactory::DrawCallback(),
666 SurfaceFactory::WillDrawCallback());
667 EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id2);
668 }
669 manager_.GetSurfaceForId(id2)->AddDestructionDependency(
670 SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
671 factory2->EvictSurface();
672 // Give local_surface_id_ a frame that references id2.
673 {
674 std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
675 CompositorFrame frame;
676 frame.render_pass_list.push_back(std::move(render_pass));
677 frame.metadata.referenced_surfaces.push_back(id2);
678 factory_->SubmitCompositorFrame(local_surface_id_, std::move(frame),
679 SurfaceFactory::DrawCallback(),
680 SurfaceFactory::WillDrawCallback());
681 }
682 factory_->EvictSurface();
683 EXPECT_TRUE(manager_.GetSurfaceForId(id2));
684 // local_surface_id_ should be retained by reference from id2.
685 EXPECT_TRUE(manager_.GetSurfaceForId(
686 SurfaceId(factory_->frame_sink_id(), local_surface_id_)));
687
688 // Satisfy last destruction dependency for id2.
689 manager_.SatisfySequence(SurfaceSequence(kAnotherArbitraryFrameSinkId, 4));
690
691 // id2 and local_surface_id_ are in a reference cycle that has no surface
692 // sequences holding on to it, so they should be destroyed.
693 EXPECT_TRUE(!manager_.GetSurfaceForId(id2));
694 EXPECT_TRUE(!manager_.GetSurfaceForId(
695 SurfaceId(factory_->frame_sink_id(), local_surface_id_)));
696
697 local_surface_id_ = LocalSurfaceId();
698 }
699
700 void CopyRequestTestCallback(bool* called,
701 std::unique_ptr<CopyOutputResult> result) {
702 *called = true;
703 }
704
705 TEST_F(SurfaceFactoryTest, DuplicateCopyRequest) {
706 {
707 std::unique_ptr<RenderPass> render_pass(RenderPass::Create());
708 CompositorFrame frame;
709 frame.render_pass_list.push_back(std::move(render_pass));
710 frame.metadata.referenced_surfaces.push_back(
711 SurfaceId(factory_->frame_sink_id(), local_surface_id_));
712 factory_->SubmitCompositorFrame(local_surface_id_, std::move(frame),
713 SurfaceFactory::DrawCallback(),
714 SurfaceFactory::WillDrawCallback());
715 EXPECT_EQ(last_created_surface_id().local_surface_id(), local_surface_id_);
716 }
717
718 bool called1 = false;
719 std::unique_ptr<CopyOutputRequest> request;
720 request = CopyOutputRequest::CreateRequest(
721 base::Bind(&CopyRequestTestCallback, &called1));
722 request->set_source(kArbitrarySourceId1);
723
724 factory_->RequestCopyOfSurface(std::move(request));
725 EXPECT_FALSE(called1);
726
727 bool called2 = false;
728 request = CopyOutputRequest::CreateRequest(
729 base::Bind(&CopyRequestTestCallback, &called2));
730 request->set_source(kArbitrarySourceId2);
731
732 factory_->RequestCopyOfSurface(std::move(request));
733 // Callbacks have different sources so neither should be called.
734 EXPECT_FALSE(called1);
735 EXPECT_FALSE(called2);
736
737 bool called3 = false;
738 request = CopyOutputRequest::CreateRequest(
739 base::Bind(&CopyRequestTestCallback, &called3));
740 request->set_source(kArbitrarySourceId1);
741
742 factory_->RequestCopyOfSurface(std::move(request));
743 // Two callbacks are from source1, so the first should be called.
744 EXPECT_TRUE(called1);
745 EXPECT_FALSE(called2);
746 EXPECT_FALSE(called3);
747
748 factory_->EvictSurface();
749 local_surface_id_ = LocalSurfaceId();
750 EXPECT_TRUE(called1);
751 EXPECT_TRUE(called2);
752 EXPECT_TRUE(called3);
753 }
754
755 // Check whether the SurfaceInfo object is created and populated correctly
756 // after the frame submission.
757 TEST_F(SurfaceFactoryTest, SurfaceInfo) {
758 CompositorFrame frame;
759
760 auto render_pass = RenderPass::Create();
761 render_pass->SetNew(1, gfx::Rect(5, 6), gfx::Rect(), gfx::Transform());
762 frame.render_pass_list.push_back(std::move(render_pass));
763
764 render_pass = RenderPass::Create();
765 render_pass->SetNew(2, gfx::Rect(7, 8), gfx::Rect(), gfx::Transform());
766 frame.render_pass_list.push_back(std::move(render_pass));
767
768 frame.metadata.device_scale_factor = 2.5f;
769
770 factory_->SubmitCompositorFrame(local_surface_id_, std::move(frame),
771 SurfaceFactory::DrawCallback(),
772 SurfaceFactory::WillDrawCallback());
773 SurfaceId expected_surface_id(factory_->frame_sink_id(), local_surface_id_);
774 EXPECT_EQ(expected_surface_id, last_surface_info_.id());
775 EXPECT_EQ(2.5f, last_surface_info_.device_scale_factor());
776 EXPECT_EQ(gfx::Size(7, 8), last_surface_info_.size_in_pixels());
777 }
778
779 } // namespace
780 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698