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

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

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

Powered by Google App Engine
This is Rietveld 408576698