Removed Polymer elements depending on web-animations-js.
[chromium-blink-merge.git] / cc / surfaces / surface_aggregator_unittest.cc
blob4771c823b291db5b3981c8c62de2cbfd2576d31c
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.
5 #include "cc/output/compositor_frame.h"
6 #include "cc/output/delegated_frame_data.h"
7 #include "cc/quads/render_pass.h"
8 #include "cc/quads/render_pass_draw_quad.h"
9 #include "cc/quads/solid_color_draw_quad.h"
10 #include "cc/quads/surface_draw_quad.h"
11 #include "cc/quads/texture_draw_quad.h"
12 #include "cc/resources/shared_bitmap_manager.h"
13 #include "cc/surfaces/surface.h"
14 #include "cc/surfaces/surface_aggregator.h"
15 #include "cc/surfaces/surface_aggregator_test_helpers.h"
16 #include "cc/surfaces/surface_factory.h"
17 #include "cc/surfaces/surface_factory_client.h"
18 #include "cc/surfaces/surface_id_allocator.h"
19 #include "cc/surfaces/surface_manager.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/render_pass_test_common.h"
23 #include "cc/test/render_pass_test_utils.h"
24 #include "cc/test/test_shared_bitmap_manager.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "third_party/skia/include/core/SkColor.h"
29 namespace cc {
30 namespace {
32 SurfaceId InvalidSurfaceId() {
33 static SurfaceId invalid;
34 invalid.id = static_cast<uint64_t>(-1);
35 return invalid;
38 gfx::Size SurfaceSize() {
39 static gfx::Size size(5, 5);
40 return size;
43 class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
44 public:
45 void ReturnResources(const ReturnedResourceArray& resources) override {}
48 class SurfaceAggregatorTest : public testing::Test {
49 public:
50 SurfaceAggregatorTest()
51 : factory_(&manager_, &empty_client_), aggregator_(&manager_, NULL) {}
53 protected:
54 SurfaceManager manager_;
55 EmptySurfaceFactoryClient empty_client_;
56 SurfaceFactory factory_;
57 SurfaceAggregator aggregator_;
60 TEST_F(SurfaceAggregatorTest, ValidSurfaceNoFrame) {
61 SurfaceId one_id(7);
62 factory_.Create(one_id, SurfaceSize());
63 scoped_ptr<CompositorFrame> frame = aggregator_.Aggregate(one_id);
64 EXPECT_FALSE(frame);
65 factory_.Destroy(one_id);
68 class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
69 public:
70 SurfaceAggregatorValidSurfaceTest() : allocator_(1u), child_allocator_(2u) {}
72 virtual void SetUp() {
73 SurfaceAggregatorTest::SetUp();
74 root_surface_id_ = allocator_.GenerateId();
75 factory_.Create(root_surface_id_, SurfaceSize());
78 virtual void TearDown() {
79 factory_.Destroy(root_surface_id_);
80 SurfaceAggregatorTest::TearDown();
83 void AggregateAndVerify(test::Pass* expected_passes,
84 size_t expected_pass_count,
85 SurfaceId* surface_ids,
86 size_t expected_surface_count) {
87 scoped_ptr<CompositorFrame> aggregated_frame =
88 aggregator_.Aggregate(root_surface_id_);
90 ASSERT_TRUE(aggregated_frame);
91 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
93 DelegatedFrameData* frame_data =
94 aggregated_frame->delegated_frame_data.get();
96 TestPassesMatchExpectations(
97 expected_passes, expected_pass_count, &frame_data->render_pass_list);
99 // Ensure no duplicate pass ids output.
100 std::set<RenderPassId> used_passes;
101 for (auto* pass : frame_data->render_pass_list) {
102 EXPECT_TRUE(used_passes.insert(pass->id).second);
105 EXPECT_EQ(expected_surface_count,
106 aggregator_.previous_contained_surfaces().size());
107 for (size_t i = 0; i < expected_surface_count; i++) {
108 EXPECT_TRUE(
109 aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
110 aggregator_.previous_contained_surfaces().end());
114 void SubmitFrame(test::Pass* passes,
115 size_t pass_count,
116 SurfaceId surface_id) {
117 RenderPassList pass_list;
118 AddPasses(&pass_list, gfx::Rect(SurfaceSize()), passes, pass_count);
120 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
121 pass_list.swap(frame_data->render_pass_list);
123 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
124 frame->delegated_frame_data = frame_data.Pass();
126 factory_.SubmitFrame(surface_id, frame.Pass(), base::Closure());
129 void QueuePassAsFrame(scoped_ptr<RenderPass> pass, SurfaceId surface_id) {
130 scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
131 delegated_frame_data->render_pass_list.push_back(pass.Pass());
133 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
134 child_frame->delegated_frame_data = delegated_frame_data.Pass();
136 factory_.SubmitFrame(surface_id, child_frame.Pass(), base::Closure());
139 protected:
140 SurfaceId root_surface_id_;
141 SurfaceIdAllocator allocator_;
142 SurfaceIdAllocator child_allocator_;
145 // Tests that a very simple frame containing only two solid color quads makes it
146 // through the aggregator correctly.
147 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) {
148 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorRED),
149 test::Quad::SolidColorQuad(SK_ColorBLUE)};
150 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
152 SubmitFrame(passes, arraysize(passes), root_surface_id_);
154 SurfaceId ids[] = {root_surface_id_};
155 AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids));
158 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {
159 test::Quad quads[][2] = {{test::Quad::SolidColorQuad(SK_ColorWHITE),
160 test::Quad::SolidColorQuad(SK_ColorLTGRAY)},
161 {test::Quad::SolidColorQuad(SK_ColorGRAY),
162 test::Quad::SolidColorQuad(SK_ColorDKGRAY)}};
163 test::Pass passes[] = {
164 test::Pass(quads[0], arraysize(quads[0]), RenderPassId(1, 1)),
165 test::Pass(quads[1], arraysize(quads[1]), RenderPassId(1, 2))};
167 SubmitFrame(passes, arraysize(passes), root_surface_id_);
169 SurfaceId ids[] = {root_surface_id_};
170 AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids));
173 // This tests very simple embedding. root_surface has a frame containing a few
174 // solid color quads and a surface quad referencing embedded_surface.
175 // embedded_surface has a frame containing only a solid color quad. The solid
176 // color quad should be aggregated into the final frame.
177 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
178 SurfaceId embedded_surface_id = allocator_.GenerateId();
179 factory_.Create(embedded_surface_id, SurfaceSize());
181 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
182 test::Pass embedded_passes[] = {
183 test::Pass(embedded_quads, arraysize(embedded_quads))};
185 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
187 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
188 test::Quad::SurfaceQuad(embedded_surface_id),
189 test::Quad::SolidColorQuad(SK_ColorBLACK)};
190 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
192 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
194 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
195 test::Quad::SolidColorQuad(SK_ColorGREEN),
196 test::Quad::SolidColorQuad(SK_ColorBLACK)};
197 test::Pass expected_passes[] = {
198 test::Pass(expected_quads, arraysize(expected_quads))};
199 SurfaceId ids[] = {root_surface_id_, embedded_surface_id};
200 AggregateAndVerify(
201 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
203 factory_.Destroy(embedded_surface_id);
206 TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
207 SurfaceId embedded_surface_id = allocator_.GenerateId();
208 factory_.Create(embedded_surface_id, SurfaceSize());
210 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
211 test::Pass embedded_passes[] = {
212 test::Pass(embedded_quads, arraysize(embedded_quads))};
214 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
215 scoped_ptr<CopyOutputRequest> copy_request(
216 CopyOutputRequest::CreateEmptyRequest());
217 CopyOutputRequest* copy_request_ptr = copy_request.get();
218 factory_.RequestCopyOfSurface(embedded_surface_id, copy_request.Pass());
220 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
221 test::Quad::SurfaceQuad(embedded_surface_id),
222 test::Quad::SolidColorQuad(SK_ColorBLACK)};
223 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
225 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
227 scoped_ptr<CompositorFrame> aggregated_frame =
228 aggregator_.Aggregate(root_surface_id_);
230 ASSERT_TRUE(aggregated_frame);
231 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
233 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
235 test::Quad expected_quads[] = {
236 test::Quad::SolidColorQuad(SK_ColorWHITE),
237 test::Quad::RenderPassQuad(frame_data->render_pass_list[0]->id),
238 test::Quad::SolidColorQuad(SK_ColorBLACK)};
239 test::Pass expected_passes[] = {
240 test::Pass(embedded_quads, arraysize(embedded_quads)),
241 test::Pass(expected_quads, arraysize(expected_quads))};
242 TestPassesMatchExpectations(expected_passes,
243 arraysize(expected_passes),
244 &frame_data->render_pass_list);
245 ASSERT_EQ(2u, frame_data->render_pass_list.size());
246 ASSERT_EQ(1u, frame_data->render_pass_list[0]->copy_requests.size());
247 DCHECK_EQ(copy_request_ptr,
248 frame_data->render_pass_list[0]->copy_requests[0]);
250 SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id};
251 EXPECT_EQ(arraysize(surface_ids),
252 aggregator_.previous_contained_surfaces().size());
253 for (size_t i = 0; i < arraysize(surface_ids); i++) {
254 EXPECT_TRUE(
255 aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
256 aggregator_.previous_contained_surfaces().end());
259 factory_.Destroy(embedded_surface_id);
262 // Root surface may contain copy requests.
263 TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
264 SurfaceId embedded_surface_id = allocator_.GenerateId();
265 factory_.Create(embedded_surface_id, SurfaceSize());
267 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
268 test::Pass embedded_passes[] = {
269 test::Pass(embedded_quads, arraysize(embedded_quads))};
271 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
272 scoped_ptr<CopyOutputRequest> copy_request(
273 CopyOutputRequest::CreateEmptyRequest());
274 CopyOutputRequest* copy_request_ptr = copy_request.get();
275 scoped_ptr<CopyOutputRequest> copy_request2(
276 CopyOutputRequest::CreateEmptyRequest());
277 CopyOutputRequest* copy_request2_ptr = copy_request2.get();
279 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
280 test::Quad::SurfaceQuad(embedded_surface_id),
281 test::Quad::SolidColorQuad(SK_ColorBLACK)};
282 test::Quad root_quads2[] = {test::Quad::SolidColorQuad(SK_ColorRED)};
283 test::Pass root_passes[] = {
284 test::Pass(root_quads, arraysize(root_quads), RenderPassId(1, 1)),
285 test::Pass(root_quads2, arraysize(root_quads2), RenderPassId(1, 2))};
287 RenderPassList pass_list;
288 AddPasses(&pass_list,
289 gfx::Rect(SurfaceSize()),
290 root_passes,
291 arraysize(root_passes));
292 pass_list[0]->copy_requests.push_back(copy_request.Pass());
293 pass_list[1]->copy_requests.push_back(copy_request2.Pass());
295 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
296 pass_list.swap(frame_data->render_pass_list);
298 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
299 frame->delegated_frame_data = frame_data.Pass();
301 factory_.SubmitFrame(root_surface_id_, frame.Pass(), base::Closure());
304 scoped_ptr<CompositorFrame> aggregated_frame =
305 aggregator_.Aggregate(root_surface_id_);
307 ASSERT_TRUE(aggregated_frame);
308 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
310 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
312 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
313 test::Quad::SolidColorQuad(SK_ColorGREEN),
314 test::Quad::SolidColorQuad(SK_ColorBLACK)};
315 test::Pass expected_passes[] = {
316 test::Pass(expected_quads, arraysize(expected_quads)),
317 test::Pass(root_quads2, arraysize(root_quads2))};
318 TestPassesMatchExpectations(expected_passes,
319 arraysize(expected_passes),
320 &frame_data->render_pass_list);
321 ASSERT_EQ(2u, frame_data->render_pass_list.size());
322 ASSERT_EQ(1u, frame_data->render_pass_list[0]->copy_requests.size());
323 DCHECK_EQ(copy_request_ptr,
324 frame_data->render_pass_list[0]->copy_requests[0]);
325 ASSERT_EQ(1u, frame_data->render_pass_list[1]->copy_requests.size());
326 DCHECK_EQ(copy_request2_ptr,
327 frame_data->render_pass_list[1]->copy_requests[0]);
329 SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id};
330 EXPECT_EQ(arraysize(surface_ids),
331 aggregator_.previous_contained_surfaces().size());
332 for (size_t i = 0; i < arraysize(surface_ids); i++) {
333 EXPECT_TRUE(
334 aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
335 aggregator_.previous_contained_surfaces().end());
338 // Ensure copy requests have been removed from root surface.
339 const CompositorFrame* original_frame =
340 manager_.GetSurfaceForId(root_surface_id_)->GetEligibleFrame();
341 RenderPassList& original_pass_list =
342 original_frame->delegated_frame_data->render_pass_list;
343 ASSERT_EQ(2u, original_pass_list.size());
344 DCHECK(original_pass_list[0]->copy_requests.empty());
345 DCHECK(original_pass_list[1]->copy_requests.empty());
347 factory_.Destroy(embedded_surface_id);
350 // This tests referencing a surface that has multiple render passes.
351 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
352 SurfaceId embedded_surface_id = child_allocator_.GenerateId();
353 factory_.Create(embedded_surface_id, SurfaceSize());
355 RenderPassId pass_ids[] = {RenderPassId(1, 1), RenderPassId(1, 2),
356 RenderPassId(1, 3)};
358 test::Quad embedded_quads[][2] = {
359 {test::Quad::SolidColorQuad(1), test::Quad::SolidColorQuad(2)},
360 {test::Quad::SolidColorQuad(3), test::Quad::RenderPassQuad(pass_ids[0])},
361 {test::Quad::SolidColorQuad(4), test::Quad::RenderPassQuad(pass_ids[1])}};
362 test::Pass embedded_passes[] = {
363 test::Pass(embedded_quads[0], arraysize(embedded_quads[0]), pass_ids[0]),
364 test::Pass(embedded_quads[1], arraysize(embedded_quads[1]), pass_ids[1]),
365 test::Pass(embedded_quads[2], arraysize(embedded_quads[2]), pass_ids[2])};
367 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
369 test::Quad root_quads[][2] = {
370 {test::Quad::SolidColorQuad(5), test::Quad::SolidColorQuad(6)},
371 {test::Quad::SurfaceQuad(embedded_surface_id),
372 test::Quad::RenderPassQuad(pass_ids[0])},
373 {test::Quad::SolidColorQuad(7), test::Quad::RenderPassQuad(pass_ids[1])}};
374 test::Pass root_passes[] = {
375 test::Pass(root_quads[0], arraysize(root_quads[0]), pass_ids[0]),
376 test::Pass(root_quads[1], arraysize(root_quads[1]), pass_ids[1]),
377 test::Pass(root_quads[2], arraysize(root_quads[2]), pass_ids[2])};
379 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
381 scoped_ptr<CompositorFrame> aggregated_frame =
382 aggregator_.Aggregate(root_surface_id_);
384 ASSERT_TRUE(aggregated_frame);
385 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
387 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
389 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
391 ASSERT_EQ(5u, aggregated_pass_list.size());
392 RenderPassId actual_pass_ids[] = {
393 aggregated_pass_list[0]->id, aggregated_pass_list[1]->id,
394 aggregated_pass_list[2]->id, aggregated_pass_list[3]->id,
395 aggregated_pass_list[4]->id};
396 for (size_t i = 0; i < 5; ++i) {
397 for (size_t j = 0; j < i; ++j) {
398 EXPECT_NE(actual_pass_ids[i], actual_pass_ids[j]);
403 SCOPED_TRACE("First pass");
404 // The first pass will just be the first pass from the root surfaces quad
405 // with no render pass quads to remap.
406 TestPassMatchesExpectations(root_passes[0], aggregated_pass_list[0]);
410 SCOPED_TRACE("Second pass");
411 // The next two passes will be from the embedded surface since we have to
412 // draw those passes before they are referenced from the render pass draw
413 // quad embedded into the root surface's second pass.
414 // First, there's the first embedded pass which doesn't reference anything
415 // else.
416 TestPassMatchesExpectations(embedded_passes[0], aggregated_pass_list[1]);
420 SCOPED_TRACE("Third pass");
421 const QuadList& third_pass_quad_list = aggregated_pass_list[2]->quad_list;
422 ASSERT_EQ(2u, third_pass_quad_list.size());
423 TestQuadMatchesExpectations(embedded_quads[1][0],
424 third_pass_quad_list.ElementAt(0));
426 // This render pass pass quad will reference the first pass from the
427 // embedded surface, which is the second pass in the aggregated frame.
428 ASSERT_EQ(DrawQuad::RENDER_PASS,
429 third_pass_quad_list.ElementAt(1)->material);
430 const RenderPassDrawQuad* third_pass_render_pass_draw_quad =
431 RenderPassDrawQuad::MaterialCast(third_pass_quad_list.ElementAt(1));
432 EXPECT_EQ(actual_pass_ids[1],
433 third_pass_render_pass_draw_quad->render_pass_id);
437 SCOPED_TRACE("Fourth pass");
438 // The fourth pass will have aggregated quads from the root surface's second
439 // pass and the embedded surface's first pass.
440 const QuadList& fourth_pass_quad_list = aggregated_pass_list[3]->quad_list;
441 ASSERT_EQ(3u, fourth_pass_quad_list.size());
443 // The first quad will be the yellow quad from the embedded surface's last
444 // pass.
445 TestQuadMatchesExpectations(embedded_quads[2][0],
446 fourth_pass_quad_list.ElementAt(0));
448 // The next quad will be a render pass quad referencing the second pass from
449 // the embedded surface, which is the third pass in the aggregated frame.
450 ASSERT_EQ(DrawQuad::RENDER_PASS,
451 fourth_pass_quad_list.ElementAt(1)->material);
452 const RenderPassDrawQuad* fourth_pass_first_render_pass_draw_quad =
453 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.ElementAt(1));
454 EXPECT_EQ(actual_pass_ids[2],
455 fourth_pass_first_render_pass_draw_quad->render_pass_id);
457 // The last quad will be a render pass quad referencing the first pass from
458 // the root surface, which is the first pass overall.
459 ASSERT_EQ(DrawQuad::RENDER_PASS,
460 fourth_pass_quad_list.ElementAt(2)->material);
461 const RenderPassDrawQuad* fourth_pass_second_render_pass_draw_quad =
462 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.ElementAt(2));
463 EXPECT_EQ(actual_pass_ids[0],
464 fourth_pass_second_render_pass_draw_quad->render_pass_id);
468 SCOPED_TRACE("Fifth pass");
469 const QuadList& fifth_pass_quad_list = aggregated_pass_list[4]->quad_list;
470 ASSERT_EQ(2u, fifth_pass_quad_list.size());
472 TestQuadMatchesExpectations(root_quads[2][0],
473 fifth_pass_quad_list.ElementAt(0));
475 // The last quad in the last pass will reference the second pass from the
476 // root surface, which after aggregating is the fourth pass in the overall
477 // list.
478 ASSERT_EQ(DrawQuad::RENDER_PASS,
479 fifth_pass_quad_list.ElementAt(1)->material);
480 const RenderPassDrawQuad* fifth_pass_render_pass_draw_quad =
481 RenderPassDrawQuad::MaterialCast(fifth_pass_quad_list.ElementAt(1));
482 EXPECT_EQ(actual_pass_ids[3],
483 fifth_pass_render_pass_draw_quad->render_pass_id);
485 factory_.Destroy(embedded_surface_id);
488 // Tests an invalid surface reference in a frame. The surface quad should just
489 // be dropped.
490 TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {
491 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
492 test::Quad::SurfaceQuad(InvalidSurfaceId()),
493 test::Quad::SolidColorQuad(SK_ColorBLUE)};
494 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
496 SubmitFrame(passes, arraysize(passes), root_surface_id_);
498 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
499 test::Quad::SolidColorQuad(SK_ColorBLUE)};
500 test::Pass expected_passes[] = {
501 test::Pass(expected_quads, arraysize(expected_quads))};
502 SurfaceId ids[] = {root_surface_id_, InvalidSurfaceId()};
503 AggregateAndVerify(
504 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
507 // Tests a reference to a valid surface with no submitted frame. This quad
508 // should also just be dropped.
509 TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) {
510 SurfaceId surface_with_no_frame_id = allocator_.GenerateId();
511 factory_.Create(surface_with_no_frame_id, gfx::Size(5, 5));
512 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
513 test::Quad::SurfaceQuad(surface_with_no_frame_id),
514 test::Quad::SolidColorQuad(SK_ColorBLUE)};
515 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
517 SubmitFrame(passes, arraysize(passes), root_surface_id_);
519 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
520 test::Quad::SolidColorQuad(SK_ColorBLUE)};
521 test::Pass expected_passes[] = {
522 test::Pass(expected_quads, arraysize(expected_quads))};
523 SurfaceId ids[] = {root_surface_id_, surface_with_no_frame_id};
524 AggregateAndVerify(
525 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
526 factory_.Destroy(surface_with_no_frame_id);
529 // Tests a surface quad referencing itself, generating a trivial cycle.
530 // The quad creating the cycle should be dropped from the final frame.
531 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {
532 test::Quad quads[] = {test::Quad::SurfaceQuad(root_surface_id_),
533 test::Quad::SolidColorQuad(SK_ColorYELLOW)};
534 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
536 SubmitFrame(passes, arraysize(passes), root_surface_id_);
538 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorYELLOW)};
539 test::Pass expected_passes[] = {
540 test::Pass(expected_quads, arraysize(expected_quads))};
541 SurfaceId ids[] = {root_surface_id_};
542 AggregateAndVerify(
543 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
546 // Tests a more complex cycle with one intermediate surface.
547 TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
548 SurfaceId child_surface_id = allocator_.GenerateId();
549 factory_.Create(child_surface_id, SurfaceSize());
551 test::Quad parent_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
552 test::Quad::SurfaceQuad(child_surface_id),
553 test::Quad::SolidColorQuad(SK_ColorCYAN)};
554 test::Pass parent_passes[] = {
555 test::Pass(parent_quads, arraysize(parent_quads))};
557 SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
559 test::Quad child_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
560 test::Quad::SurfaceQuad(root_surface_id_),
561 test::Quad::SolidColorQuad(SK_ColorMAGENTA)};
562 test::Pass child_passes[] = {test::Pass(child_quads, arraysize(child_quads))};
564 SubmitFrame(child_passes, arraysize(child_passes), child_surface_id);
566 // The child surface's reference to the root_surface_ will be dropped, so
567 // we'll end up with:
568 // SK_ColorBLUE from the parent
569 // SK_ColorGREEN from the child
570 // SK_ColorMAGENTA from the child
571 // SK_ColorCYAN from the parent
572 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
573 test::Quad::SolidColorQuad(SK_ColorGREEN),
574 test::Quad::SolidColorQuad(SK_ColorMAGENTA),
575 test::Quad::SolidColorQuad(SK_ColorCYAN)};
576 test::Pass expected_passes[] = {
577 test::Pass(expected_quads, arraysize(expected_quads))};
578 SurfaceId ids[] = {root_surface_id_, child_surface_id};
579 AggregateAndVerify(
580 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
581 factory_.Destroy(child_surface_id);
584 // Tests that we map render pass IDs from different surfaces into a unified
585 // namespace and update RenderPassDrawQuad's id references to match.
586 TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
587 SurfaceId child_surface_id = allocator_.GenerateId();
588 factory_.Create(child_surface_id, SurfaceSize());
590 RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
591 test::Quad child_quad[][1] = {{test::Quad::SolidColorQuad(SK_ColorGREEN)},
592 {test::Quad::RenderPassQuad(child_pass_id[0])}};
593 test::Pass surface_passes[] = {
594 test::Pass(child_quad[0], arraysize(child_quad[0]), child_pass_id[0]),
595 test::Pass(child_quad[1], arraysize(child_quad[1]), child_pass_id[1])};
597 SubmitFrame(surface_passes, arraysize(surface_passes), child_surface_id);
599 // Pass IDs from the parent surface may collide with ones from the child.
600 RenderPassId parent_pass_id[] = {RenderPassId(2, 1), RenderPassId(1, 2)};
601 test::Quad parent_quad[][1] = {
602 {test::Quad::SurfaceQuad(child_surface_id)},
603 {test::Quad::RenderPassQuad(parent_pass_id[0])}};
604 test::Pass parent_passes[] = {
605 test::Pass(parent_quad[0], arraysize(parent_quad[0]), parent_pass_id[0]),
606 test::Pass(parent_quad[1], arraysize(parent_quad[1]), parent_pass_id[1])};
608 SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
609 scoped_ptr<CompositorFrame> aggregated_frame =
610 aggregator_.Aggregate(root_surface_id_);
612 ASSERT_TRUE(aggregated_frame);
613 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
615 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
617 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
619 ASSERT_EQ(3u, aggregated_pass_list.size());
620 RenderPassId actual_pass_ids[] = {aggregated_pass_list[0]->id,
621 aggregated_pass_list[1]->id,
622 aggregated_pass_list[2]->id};
623 // Make sure the aggregated frame's pass IDs are all unique.
624 for (size_t i = 0; i < 3; ++i) {
625 for (size_t j = 0; j < i; ++j) {
626 EXPECT_NE(actual_pass_ids[j], actual_pass_ids[i]) << "pass ids " << i
627 << " and " << j;
631 // Make sure the render pass quads reference the remapped pass IDs.
632 DrawQuad* render_pass_quads[] = {aggregated_pass_list[1]->quad_list.front(),
633 aggregated_pass_list[2]->quad_list.front()};
634 ASSERT_EQ(render_pass_quads[0]->material, DrawQuad::RENDER_PASS);
635 EXPECT_EQ(
636 actual_pass_ids[0],
637 RenderPassDrawQuad::MaterialCast(render_pass_quads[0])->render_pass_id);
639 ASSERT_EQ(render_pass_quads[1]->material, DrawQuad::RENDER_PASS);
640 EXPECT_EQ(
641 actual_pass_ids[1],
642 RenderPassDrawQuad::MaterialCast(render_pass_quads[1])->render_pass_id);
643 factory_.Destroy(child_surface_id);
646 void AddSolidColorQuadWithBlendMode(const gfx::Size& size,
647 RenderPass* pass,
648 const SkXfermode::Mode blend_mode) {
649 const gfx::Transform content_to_target_transform;
650 const gfx::Size content_bounds(size);
651 const gfx::Rect visible_content_rect(size);
652 const gfx::Rect clip_rect(size);
654 bool is_clipped = false;
655 float opacity = 1.f;
657 bool force_anti_aliasing_off = false;
658 SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
659 sqs->SetAll(content_to_target_transform,
660 content_bounds,
661 visible_content_rect,
662 clip_rect,
663 is_clipped,
664 opacity,
665 blend_mode,
668 SolidColorDrawQuad* color_quad =
669 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
670 color_quad->SetNew(pass->shared_quad_state_list.back(),
671 visible_content_rect,
672 visible_content_rect,
673 SK_ColorGREEN,
674 force_anti_aliasing_off);
677 // This tests that we update shared quad state pointers correctly within
678 // aggregated passes. The shared quad state list on the aggregated pass will
679 // include the shared quad states from each pass in one list so the quads will
680 // end up pointed to shared quad state objects at different offsets. This test
681 // uses the blend_mode value stored on the shared quad state to track the shared
682 // quad state, but anything saved on the shared quad state would work.
684 // This test has 4 surfaces in the following structure:
685 // root_surface -> quad with kClear_Mode,
686 // [child_one_surface],
687 // quad with kDstOver_Mode,
688 // [child_two_surface],
689 // quad with kDstIn_Mode
690 // child_one_surface -> quad with kSrc_Mode,
691 // [grandchild_surface],
692 // quad with kSrcOver_Mode
693 // child_two_surface -> quad with kSrcIn_Mode
694 // grandchild_surface -> quad with kDst_Mode
696 // Resulting in the following aggregated pass:
697 // quad_root_0 - blend_mode kClear_Mode
698 // quad_child_one_0 - blend_mode kSrc_Mode
699 // quad_grandchild_0 - blend_mode kDst_Mode
700 // quad_child_one_1 - blend_mode kSrcOver_Mode
701 // quad_root_1 - blend_mode kDstOver_Mode
702 // quad_child_two_0 - blend_mode kSrcIn_Mode
703 // quad_root_2 - blend_mode kDstIn_Mode
704 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
705 const SkXfermode::Mode blend_modes[] = {SkXfermode::kClear_Mode, // 0
706 SkXfermode::kSrc_Mode, // 1
707 SkXfermode::kDst_Mode, // 2
708 SkXfermode::kSrcOver_Mode, // 3
709 SkXfermode::kDstOver_Mode, // 4
710 SkXfermode::kSrcIn_Mode, // 5
711 SkXfermode::kDstIn_Mode, // 6
714 RenderPassId pass_id(1, 1);
715 SurfaceId grandchild_surface_id = allocator_.GenerateId();
716 factory_.Create(grandchild_surface_id, SurfaceSize());
717 scoped_ptr<RenderPass> grandchild_pass = RenderPass::Create();
718 gfx::Rect output_rect(SurfaceSize());
719 gfx::Rect damage_rect(SurfaceSize());
720 gfx::Transform transform_to_root_target;
721 grandchild_pass->SetNew(
722 pass_id, output_rect, damage_rect, transform_to_root_target);
723 AddSolidColorQuadWithBlendMode(
724 SurfaceSize(), grandchild_pass.get(), blend_modes[2]);
725 QueuePassAsFrame(grandchild_pass.Pass(), grandchild_surface_id);
727 SurfaceId child_one_surface_id = allocator_.GenerateId();
728 factory_.Create(child_one_surface_id, SurfaceSize());
730 scoped_ptr<RenderPass> child_one_pass = RenderPass::Create();
731 child_one_pass->SetNew(
732 pass_id, output_rect, damage_rect, transform_to_root_target);
733 AddSolidColorQuadWithBlendMode(
734 SurfaceSize(), child_one_pass.get(), blend_modes[1]);
735 SurfaceDrawQuad* grandchild_surface_quad =
736 child_one_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
737 grandchild_surface_quad->SetNew(child_one_pass->shared_quad_state_list.back(),
738 gfx::Rect(SurfaceSize()),
739 gfx::Rect(SurfaceSize()),
740 grandchild_surface_id);
741 AddSolidColorQuadWithBlendMode(
742 SurfaceSize(), child_one_pass.get(), blend_modes[3]);
743 QueuePassAsFrame(child_one_pass.Pass(), child_one_surface_id);
745 SurfaceId child_two_surface_id = allocator_.GenerateId();
746 factory_.Create(child_two_surface_id, SurfaceSize());
748 scoped_ptr<RenderPass> child_two_pass = RenderPass::Create();
749 child_two_pass->SetNew(
750 pass_id, output_rect, damage_rect, transform_to_root_target);
751 AddSolidColorQuadWithBlendMode(
752 SurfaceSize(), child_two_pass.get(), blend_modes[5]);
753 QueuePassAsFrame(child_two_pass.Pass(), child_two_surface_id);
755 scoped_ptr<RenderPass> root_pass = RenderPass::Create();
756 root_pass->SetNew(
757 pass_id, output_rect, damage_rect, transform_to_root_target);
759 AddSolidColorQuadWithBlendMode(
760 SurfaceSize(), root_pass.get(), blend_modes[0]);
761 SurfaceDrawQuad* child_one_surface_quad =
762 root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
763 child_one_surface_quad->SetNew(root_pass->shared_quad_state_list.back(),
764 gfx::Rect(SurfaceSize()),
765 gfx::Rect(SurfaceSize()),
766 child_one_surface_id);
767 AddSolidColorQuadWithBlendMode(
768 SurfaceSize(), root_pass.get(), blend_modes[4]);
769 SurfaceDrawQuad* child_two_surface_quad =
770 root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
771 child_two_surface_quad->SetNew(root_pass->shared_quad_state_list.back(),
772 gfx::Rect(SurfaceSize()),
773 gfx::Rect(SurfaceSize()),
774 child_two_surface_id);
775 AddSolidColorQuadWithBlendMode(
776 SurfaceSize(), root_pass.get(), blend_modes[6]);
778 QueuePassAsFrame(root_pass.Pass(), root_surface_id_);
780 scoped_ptr<CompositorFrame> aggregated_frame =
781 aggregator_.Aggregate(root_surface_id_);
783 ASSERT_TRUE(aggregated_frame);
784 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
786 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
788 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
790 ASSERT_EQ(1u, aggregated_pass_list.size());
792 const QuadList& aggregated_quad_list = aggregated_pass_list[0]->quad_list;
794 ASSERT_EQ(7u, aggregated_quad_list.size());
796 for (auto iter = aggregated_quad_list.cbegin();
797 iter != aggregated_quad_list.cend();
798 ++iter) {
799 EXPECT_EQ(blend_modes[iter.index()], iter->shared_quad_state->blend_mode)
800 << iter.index();
802 factory_.Destroy(child_one_surface_id);
803 factory_.Destroy(child_two_surface_id);
804 factory_.Destroy(grandchild_surface_id);
807 // This tests that when aggregating a frame with multiple render passes that we
808 // map the transforms for the root pass but do not modify the transform on child
809 // passes.
811 // The root surface has one pass with a surface quad transformed by +10 in the y
812 // direction.
814 // The child surface has two passes. The first pass has a quad with a transform
815 // of +5 in the x direction. The second pass has a reference to the first pass'
816 // pass id and a transform of +8 in the x direction.
818 // After aggregation, the child surface's root pass quad should have both
819 // transforms concatenated for a total transform of +8 x, +10 y. The
820 // contributing render pass' transform in the aggregate frame should not be
821 // affected.
822 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
823 SurfaceId child_surface_id = allocator_.GenerateId();
824 factory_.Create(child_surface_id, SurfaceSize());
825 RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
826 test::Quad child_quads[][1] = {
827 {test::Quad::SolidColorQuad(SK_ColorGREEN)},
828 {test::Quad::RenderPassQuad(child_pass_id[0])}};
829 test::Pass child_passes[] = {
830 test::Pass(child_quads[0], arraysize(child_quads[0]), child_pass_id[0]),
831 test::Pass(child_quads[1], arraysize(child_quads[1]), child_pass_id[1])};
833 RenderPassList child_pass_list;
834 AddPasses(&child_pass_list,
835 gfx::Rect(SurfaceSize()),
836 child_passes,
837 arraysize(child_passes));
839 RenderPass* child_nonroot_pass = child_pass_list.at(0u);
840 child_nonroot_pass->transform_to_root_target.Translate(8, 0);
841 SharedQuadState* child_nonroot_pass_sqs =
842 child_nonroot_pass->shared_quad_state_list.front();
843 child_nonroot_pass_sqs->content_to_target_transform.Translate(5, 0);
845 RenderPass* child_root_pass = child_pass_list.at(1u);
846 SharedQuadState* child_root_pass_sqs =
847 child_root_pass->shared_quad_state_list.front();
848 child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
849 child_root_pass_sqs->is_clipped = true;
850 child_root_pass_sqs->clip_rect = gfx::Rect(0, 0, 5, 5);
852 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
853 child_pass_list.swap(child_frame_data->render_pass_list);
855 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
856 child_frame->delegated_frame_data = child_frame_data.Pass();
858 factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
860 test::Quad root_quads[] = {test::Quad::SolidColorQuad(1),
861 test::Quad::SurfaceQuad(child_surface_id)};
862 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
864 RenderPassList root_pass_list;
865 AddPasses(&root_pass_list,
866 gfx::Rect(SurfaceSize()),
867 root_passes,
868 arraysize(root_passes));
870 root_pass_list.at(0)
871 ->shared_quad_state_list.front()
872 ->content_to_target_transform.Translate(0, 7);
873 root_pass_list.at(0)
874 ->shared_quad_state_list.ElementAt(1)
875 ->content_to_target_transform.Translate(0, 10);
877 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
878 root_pass_list.swap(root_frame_data->render_pass_list);
880 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
881 root_frame->delegated_frame_data = root_frame_data.Pass();
883 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
885 scoped_ptr<CompositorFrame> aggregated_frame =
886 aggregator_.Aggregate(root_surface_id_);
888 ASSERT_TRUE(aggregated_frame);
889 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
891 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
893 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
895 ASSERT_EQ(2u, aggregated_pass_list.size());
897 ASSERT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
899 // The first pass should have one shared quad state for the one solid color
900 // quad.
901 EXPECT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
902 // The second (root) pass should have just two shared quad states. We'll
903 // verify the properties through the quads.
904 EXPECT_EQ(2u, aggregated_pass_list[1]->shared_quad_state_list.size());
906 SharedQuadState* aggregated_first_pass_sqs =
907 aggregated_pass_list[0]->shared_quad_state_list.front();
909 // The first pass's transform should be unaffected by the embedding and still
910 // be a translation by +5 in the x direction.
911 gfx::Transform expected_aggregated_first_pass_sqs_transform;
912 expected_aggregated_first_pass_sqs_transform.Translate(5, 0);
913 EXPECT_EQ(expected_aggregated_first_pass_sqs_transform.ToString(),
914 aggregated_first_pass_sqs->content_to_target_transform.ToString());
916 // The first pass's transform to the root target should include the aggregated
917 // transform.
918 gfx::Transform expected_first_pass_transform_to_root_target;
919 expected_first_pass_transform_to_root_target.Translate(8, 10);
920 EXPECT_EQ(expected_first_pass_transform_to_root_target.ToString(),
921 aggregated_pass_list[0]->transform_to_root_target.ToString());
923 ASSERT_EQ(2u, aggregated_pass_list[1]->quad_list.size());
925 gfx::Transform expected_root_pass_quad_transforms[2];
926 // The first quad in the root pass is the solid color quad from the original
927 // root surface. Its transform should be unaffected by the aggregation and
928 // still be +7 in the y direction.
929 expected_root_pass_quad_transforms[0].Translate(0, 7);
930 // The second quad in the root pass is aggregated from the child surface so
931 // its transform should be the combination of its original translation (0, 10)
932 // and the child surface draw quad's translation (8, 0).
933 expected_root_pass_quad_transforms[1].Translate(8, 10);
935 for (auto iter = aggregated_pass_list[1]->quad_list.cbegin();
936 iter != aggregated_pass_list[1]->quad_list.cend();
937 ++iter) {
938 EXPECT_EQ(expected_root_pass_quad_transforms[iter.index()].ToString(),
939 iter->quadTransform().ToString())
940 << iter.index();
943 EXPECT_TRUE(
944 aggregated_pass_list[1]->shared_quad_state_list.ElementAt(1)->is_clipped);
946 // The second quad in the root pass is aggregated from the child, so its
947 // clip rect must be transformed by the child's translation.
948 EXPECT_EQ(gfx::Rect(0, 10, 5, 5).ToString(),
949 aggregated_pass_list[1]
950 ->shared_quad_state_list.ElementAt(1)
951 ->clip_rect.ToString());
953 factory_.Destroy(child_surface_id);
956 // Tests that damage rects are aggregated correctly when surfaces change.
957 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
958 SurfaceId child_surface_id = allocator_.GenerateId();
959 factory_.Create(child_surface_id, SurfaceSize());
960 RenderPassId child_pass_id = RenderPassId(1, 1);
961 test::Quad child_quads[] = {test::Quad::RenderPassQuad(child_pass_id)};
962 test::Pass child_passes[] = {
963 test::Pass(child_quads, arraysize(child_quads), child_pass_id)};
965 RenderPassList child_pass_list;
966 AddPasses(&child_pass_list,
967 gfx::Rect(SurfaceSize()),
968 child_passes,
969 arraysize(child_passes));
971 RenderPass* child_root_pass = child_pass_list.at(0u);
972 SharedQuadState* child_root_pass_sqs =
973 child_root_pass->shared_quad_state_list.front();
974 child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
976 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
977 child_pass_list.swap(child_frame_data->render_pass_list);
979 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
980 child_frame->delegated_frame_data = child_frame_data.Pass();
982 factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
984 test::Quad root_quads[] = {test::Quad::SurfaceQuad(child_surface_id)};
985 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
987 RenderPassList root_pass_list;
988 AddPasses(&root_pass_list,
989 gfx::Rect(SurfaceSize()),
990 root_passes,
991 arraysize(root_passes));
993 root_pass_list.at(0)
994 ->shared_quad_state_list.front()
995 ->content_to_target_transform.Translate(0, 10);
996 root_pass_list.at(0)->damage_rect = gfx::Rect(5, 5, 10, 10);
998 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
999 root_pass_list.swap(root_frame_data->render_pass_list);
1001 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1002 root_frame->delegated_frame_data = root_frame_data.Pass();
1004 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
1006 scoped_ptr<CompositorFrame> aggregated_frame =
1007 aggregator_.Aggregate(root_surface_id_);
1009 ASSERT_TRUE(aggregated_frame);
1010 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1012 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
1014 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1016 ASSERT_EQ(1u, aggregated_pass_list.size());
1018 // Damage rect for first aggregation should contain entire root surface.
1019 EXPECT_TRUE(
1020 aggregated_pass_list[0]->damage_rect.Contains(gfx::Rect(SurfaceSize())));
1023 AddPasses(&child_pass_list,
1024 gfx::Rect(SurfaceSize()),
1025 child_passes,
1026 arraysize(child_passes));
1028 RenderPass* child_root_pass = child_pass_list.at(0u);
1029 SharedQuadState* child_root_pass_sqs =
1030 child_root_pass->shared_quad_state_list.front();
1031 child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
1032 child_root_pass->damage_rect = gfx::Rect(10, 10, 10, 10);
1034 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
1035 child_pass_list.swap(child_frame_data->render_pass_list);
1037 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
1038 child_frame->delegated_frame_data = child_frame_data.Pass();
1040 factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
1042 scoped_ptr<CompositorFrame> aggregated_frame =
1043 aggregator_.Aggregate(root_surface_id_);
1045 ASSERT_TRUE(aggregated_frame);
1046 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1048 DelegatedFrameData* frame_data =
1049 aggregated_frame->delegated_frame_data.get();
1051 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1053 ASSERT_EQ(1u, aggregated_pass_list.size());
1055 // Outer surface didn't change, so transformed inner damage rect should be
1056 // used.
1057 EXPECT_EQ(gfx::Rect(10, 20, 10, 10).ToString(),
1058 aggregated_pass_list[0]->damage_rect.ToString());
1062 RenderPassList root_pass_list;
1063 AddPasses(&root_pass_list,
1064 gfx::Rect(SurfaceSize()),
1065 root_passes,
1066 arraysize(root_passes));
1068 root_pass_list.at(0)
1069 ->shared_quad_state_list.front()
1070 ->content_to_target_transform.Translate(0, 10);
1071 root_pass_list.at(0)->damage_rect = gfx::Rect(0, 0, 1, 1);
1073 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1074 root_pass_list.swap(root_frame_data->render_pass_list);
1076 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1077 root_frame->delegated_frame_data = root_frame_data.Pass();
1079 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
1083 RenderPassList root_pass_list;
1084 AddPasses(&root_pass_list,
1085 gfx::Rect(SurfaceSize()),
1086 root_passes,
1087 arraysize(root_passes));
1089 root_pass_list.at(0)
1090 ->shared_quad_state_list.front()
1091 ->content_to_target_transform.Translate(0, 10);
1092 root_pass_list.at(0)->damage_rect = gfx::Rect(1, 1, 1, 1);
1094 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1095 root_pass_list.swap(root_frame_data->render_pass_list);
1097 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1098 root_frame->delegated_frame_data = root_frame_data.Pass();
1100 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
1102 scoped_ptr<CompositorFrame> aggregated_frame =
1103 aggregator_.Aggregate(root_surface_id_);
1105 ASSERT_TRUE(aggregated_frame);
1106 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1108 DelegatedFrameData* frame_data =
1109 aggregated_frame->delegated_frame_data.get();
1111 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1113 ASSERT_EQ(1u, aggregated_pass_list.size());
1115 // The root surface was enqueued without being aggregated once, so it should
1116 // be treated as completely damaged.
1117 EXPECT_TRUE(aggregated_pass_list[0]->damage_rect.Contains(
1118 gfx::Rect(SurfaceSize())));
1121 factory_.Destroy(child_surface_id);
1124 class SurfaceAggregatorWithResourcesTest : public testing::Test {
1125 public:
1126 virtual void SetUp() {
1127 output_surface_ = FakeOutputSurface::CreateSoftware(
1128 make_scoped_ptr(new SoftwareOutputDevice));
1129 output_surface_->BindToClient(&output_surface_client_);
1130 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
1132 resource_provider_ = ResourceProvider::Create(output_surface_.get(),
1133 shared_bitmap_manager_.get(),
1134 NULL,
1135 NULL,
1137 false,
1140 aggregator_.reset(
1141 new SurfaceAggregator(&manager_, resource_provider_.get()));
1144 protected:
1145 SurfaceManager manager_;
1146 FakeOutputSurfaceClient output_surface_client_;
1147 scoped_ptr<OutputSurface> output_surface_;
1148 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
1149 scoped_ptr<ResourceProvider> resource_provider_;
1150 scoped_ptr<SurfaceAggregator> aggregator_;
1153 class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient {
1154 public:
1155 ResourceTrackingSurfaceFactoryClient() {}
1156 ~ResourceTrackingSurfaceFactoryClient() override {}
1158 void ReturnResources(const ReturnedResourceArray& resources) override {
1159 returned_resources_ = resources;
1162 ReturnedResourceArray returned_resources() const {
1163 return returned_resources_;
1166 private:
1167 ReturnedResourceArray returned_resources_;
1169 DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient);
1172 void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids,
1173 size_t num_resource_ids,
1174 SurfaceFactory* factory,
1175 SurfaceId surface_id) {
1176 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
1177 scoped_ptr<RenderPass> pass = RenderPass::Create();
1178 pass->id = RenderPassId(1, 1);
1179 SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
1180 for (size_t i = 0u; i < num_resource_ids; ++i) {
1181 TransferableResource resource;
1182 resource.id = resource_ids[i];
1183 resource.is_software = true;
1184 frame_data->resource_list.push_back(resource);
1185 TextureDrawQuad* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
1186 const gfx::Rect rect;
1187 const gfx::Rect opaque_rect;
1188 const gfx::Rect visible_rect;
1189 bool needs_blending = false;
1190 bool premultiplied_alpha = false;
1191 const gfx::PointF uv_top_left;
1192 const gfx::PointF uv_bottom_right;
1193 SkColor background_color = SK_ColorGREEN;
1194 const float vertex_opacity[4] = {0.f, 0.f, 1.f, 1.f};
1195 bool flipped = false;
1196 quad->SetAll(sqs,
1197 rect,
1198 opaque_rect,
1199 visible_rect,
1200 needs_blending,
1201 resource_ids[i],
1202 premultiplied_alpha,
1203 uv_top_left,
1204 uv_bottom_right,
1205 background_color,
1206 vertex_opacity,
1207 flipped);
1209 quad->shared_quad_state = sqs;
1211 frame_data->render_pass_list.push_back(pass.Pass());
1212 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
1213 frame->delegated_frame_data = frame_data.Pass();
1214 factory->SubmitFrame(surface_id, frame.Pass(), base::Closure());
1217 TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
1218 ResourceTrackingSurfaceFactoryClient client;
1219 SurfaceFactory factory(&manager_, &client);
1220 SurfaceId surface_id(7u);
1221 factory.Create(surface_id, SurfaceSize());
1223 ResourceProvider::ResourceId ids[] = {11, 12, 13};
1224 SubmitFrameWithResources(ids, arraysize(ids), &factory, surface_id);
1226 scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id);
1228 // Nothing should be available to be returned yet.
1229 EXPECT_TRUE(client.returned_resources().empty());
1231 SubmitFrameWithResources(NULL, 0u, &factory, surface_id);
1233 frame = aggregator_->Aggregate(surface_id);
1235 ASSERT_EQ(3u, client.returned_resources().size());
1236 ResourceProvider::ResourceId returned_ids[3];
1237 for (size_t i = 0; i < 3; ++i) {
1238 returned_ids[i] = client.returned_resources()[i].id;
1240 EXPECT_THAT(returned_ids,
1241 testing::WhenSorted(testing::ElementsAreArray(ids)));
1242 factory.Destroy(surface_id);
1245 } // namespace
1246 } // namespace cc