Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / cc / surfaces / surface_aggregator_unittest.cc
blob2e47708415c8d8a21beac71bfe4596176f0ce614
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, OpacityCopied) {
159 SurfaceId embedded_surface_id = allocator_.GenerateId();
160 factory_.Create(embedded_surface_id, SurfaceSize());
162 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
163 test::Pass embedded_passes[] = {
164 test::Pass(embedded_quads, arraysize(embedded_quads))};
166 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
168 test::Quad quads[] = {test::Quad::SurfaceQuad(embedded_surface_id, .5f)};
169 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
171 SubmitFrame(passes, arraysize(passes), root_surface_id_);
173 scoped_ptr<CompositorFrame> aggregated_frame =
174 aggregator_.Aggregate(root_surface_id_);
176 ASSERT_TRUE(aggregated_frame);
177 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
179 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
181 RenderPassList& render_pass_list(frame_data->render_pass_list);
182 ASSERT_EQ(1u, render_pass_list.size());
183 SharedQuadStateList& shared_quad_state_list(
184 render_pass_list[0]->shared_quad_state_list);
185 ASSERT_EQ(1u, shared_quad_state_list.size());
186 EXPECT_EQ(.5f, shared_quad_state_list.ElementAt(0)->opacity);
188 factory_.Destroy(embedded_surface_id);
191 TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCombinedWithNesting) {
192 SurfaceId surface_id1 = allocator_.GenerateId();
193 factory_.Create(surface_id1, SurfaceSize());
194 SurfaceId surface_id2 = allocator_.GenerateId();
195 factory_.Create(surface_id2, SurfaceSize());
197 // |surface_id1| is color quad.
199 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
200 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
201 SubmitFrame(passes, arraysize(passes), surface_id1);
204 // |surface_id2| has a color quad and a surface quad using |surface_id1| at .5
205 // opacity.
207 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
208 test::Quad::SurfaceQuad(surface_id1, .5f)};
209 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
210 SubmitFrame(passes, arraysize(passes), surface_id2);
213 // Another frame with a surface referencing |surface_id2| @ .6 opacity.
215 test::Quad quads[] = {test::Quad::SurfaceQuad(surface_id2, .6f)};
216 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
217 SubmitFrame(passes, arraysize(passes), root_surface_id_);
220 scoped_ptr<CompositorFrame> aggregated_frame =
221 aggregator_.Aggregate(root_surface_id_);
223 ASSERT_TRUE(aggregated_frame);
224 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
226 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
228 RenderPassList& render_pass_list(frame_data->render_pass_list);
229 ASSERT_EQ(1u, render_pass_list.size());
230 SharedQuadStateList& shared_quad_state_list(
231 render_pass_list[0]->shared_quad_state_list);
232 ASSERT_EQ(2u, shared_quad_state_list.size());
233 EXPECT_EQ(.6f, shared_quad_state_list.ElementAt(0)->opacity);
234 EXPECT_EQ(.3f, shared_quad_state_list.ElementAt(1)->opacity);
236 factory_.Destroy(surface_id1);
237 factory_.Destroy(surface_id2);
240 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {
241 test::Quad quads[][2] = {{test::Quad::SolidColorQuad(SK_ColorWHITE),
242 test::Quad::SolidColorQuad(SK_ColorLTGRAY)},
243 {test::Quad::SolidColorQuad(SK_ColorGRAY),
244 test::Quad::SolidColorQuad(SK_ColorDKGRAY)}};
245 test::Pass passes[] = {
246 test::Pass(quads[0], arraysize(quads[0]), RenderPassId(1, 1)),
247 test::Pass(quads[1], arraysize(quads[1]), RenderPassId(1, 2))};
249 SubmitFrame(passes, arraysize(passes), root_surface_id_);
251 SurfaceId ids[] = {root_surface_id_};
252 AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids));
255 // This tests very simple embedding. root_surface has a frame containing a few
256 // solid color quads and a surface quad referencing embedded_surface.
257 // embedded_surface has a frame containing only a solid color quad. The solid
258 // color quad should be aggregated into the final frame.
259 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
260 SurfaceId embedded_surface_id = allocator_.GenerateId();
261 factory_.Create(embedded_surface_id, SurfaceSize());
263 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
264 test::Pass embedded_passes[] = {
265 test::Pass(embedded_quads, arraysize(embedded_quads))};
267 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
269 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
270 test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
271 test::Quad::SolidColorQuad(SK_ColorBLACK)};
272 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
274 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
276 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
277 test::Quad::SolidColorQuad(SK_ColorGREEN),
278 test::Quad::SolidColorQuad(SK_ColorBLACK)};
279 test::Pass expected_passes[] = {
280 test::Pass(expected_quads, arraysize(expected_quads))};
281 SurfaceId ids[] = {root_surface_id_, embedded_surface_id};
282 AggregateAndVerify(
283 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
285 factory_.Destroy(embedded_surface_id);
288 TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
289 SurfaceId embedded_surface_id = allocator_.GenerateId();
290 factory_.Create(embedded_surface_id, SurfaceSize());
292 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
293 test::Pass embedded_passes[] = {
294 test::Pass(embedded_quads, arraysize(embedded_quads))};
296 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
297 scoped_ptr<CopyOutputRequest> copy_request(
298 CopyOutputRequest::CreateEmptyRequest());
299 CopyOutputRequest* copy_request_ptr = copy_request.get();
300 factory_.RequestCopyOfSurface(embedded_surface_id, copy_request.Pass());
302 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
303 test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
304 test::Quad::SolidColorQuad(SK_ColorBLACK)};
305 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
307 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
309 scoped_ptr<CompositorFrame> aggregated_frame =
310 aggregator_.Aggregate(root_surface_id_);
312 ASSERT_TRUE(aggregated_frame);
313 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
315 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
317 test::Quad expected_quads[] = {
318 test::Quad::SolidColorQuad(SK_ColorWHITE),
319 test::Quad::RenderPassQuad(frame_data->render_pass_list[0]->id),
320 test::Quad::SolidColorQuad(SK_ColorBLACK)};
321 test::Pass expected_passes[] = {
322 test::Pass(embedded_quads, arraysize(embedded_quads)),
323 test::Pass(expected_quads, arraysize(expected_quads))};
324 TestPassesMatchExpectations(expected_passes,
325 arraysize(expected_passes),
326 &frame_data->render_pass_list);
327 ASSERT_EQ(2u, frame_data->render_pass_list.size());
328 ASSERT_EQ(1u, frame_data->render_pass_list[0]->copy_requests.size());
329 DCHECK_EQ(copy_request_ptr,
330 frame_data->render_pass_list[0]->copy_requests[0]);
332 SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id};
333 EXPECT_EQ(arraysize(surface_ids),
334 aggregator_.previous_contained_surfaces().size());
335 for (size_t i = 0; i < arraysize(surface_ids); i++) {
336 EXPECT_TRUE(
337 aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
338 aggregator_.previous_contained_surfaces().end());
341 factory_.Destroy(embedded_surface_id);
344 // Root surface may contain copy requests.
345 TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
346 SurfaceId embedded_surface_id = allocator_.GenerateId();
347 factory_.Create(embedded_surface_id, SurfaceSize());
349 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
350 test::Pass embedded_passes[] = {
351 test::Pass(embedded_quads, arraysize(embedded_quads))};
353 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
354 scoped_ptr<CopyOutputRequest> copy_request(
355 CopyOutputRequest::CreateEmptyRequest());
356 CopyOutputRequest* copy_request_ptr = copy_request.get();
357 scoped_ptr<CopyOutputRequest> copy_request2(
358 CopyOutputRequest::CreateEmptyRequest());
359 CopyOutputRequest* copy_request2_ptr = copy_request2.get();
361 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
362 test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
363 test::Quad::SolidColorQuad(SK_ColorBLACK)};
364 test::Quad root_quads2[] = {test::Quad::SolidColorQuad(SK_ColorRED)};
365 test::Pass root_passes[] = {
366 test::Pass(root_quads, arraysize(root_quads), RenderPassId(1, 1)),
367 test::Pass(root_quads2, arraysize(root_quads2), RenderPassId(1, 2))};
369 RenderPassList pass_list;
370 AddPasses(&pass_list,
371 gfx::Rect(SurfaceSize()),
372 root_passes,
373 arraysize(root_passes));
374 pass_list[0]->copy_requests.push_back(copy_request.Pass());
375 pass_list[1]->copy_requests.push_back(copy_request2.Pass());
377 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
378 pass_list.swap(frame_data->render_pass_list);
380 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
381 frame->delegated_frame_data = frame_data.Pass();
383 factory_.SubmitFrame(root_surface_id_, frame.Pass(), base::Closure());
386 scoped_ptr<CompositorFrame> aggregated_frame =
387 aggregator_.Aggregate(root_surface_id_);
389 ASSERT_TRUE(aggregated_frame);
390 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
392 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
394 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
395 test::Quad::SolidColorQuad(SK_ColorGREEN),
396 test::Quad::SolidColorQuad(SK_ColorBLACK)};
397 test::Pass expected_passes[] = {
398 test::Pass(expected_quads, arraysize(expected_quads)),
399 test::Pass(root_quads2, arraysize(root_quads2))};
400 TestPassesMatchExpectations(expected_passes,
401 arraysize(expected_passes),
402 &frame_data->render_pass_list);
403 ASSERT_EQ(2u, frame_data->render_pass_list.size());
404 ASSERT_EQ(1u, frame_data->render_pass_list[0]->copy_requests.size());
405 DCHECK_EQ(copy_request_ptr,
406 frame_data->render_pass_list[0]->copy_requests[0]);
407 ASSERT_EQ(1u, frame_data->render_pass_list[1]->copy_requests.size());
408 DCHECK_EQ(copy_request2_ptr,
409 frame_data->render_pass_list[1]->copy_requests[0]);
411 SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id};
412 EXPECT_EQ(arraysize(surface_ids),
413 aggregator_.previous_contained_surfaces().size());
414 for (size_t i = 0; i < arraysize(surface_ids); i++) {
415 EXPECT_TRUE(
416 aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
417 aggregator_.previous_contained_surfaces().end());
420 // Ensure copy requests have been removed from root surface.
421 const CompositorFrame* original_frame =
422 manager_.GetSurfaceForId(root_surface_id_)->GetEligibleFrame();
423 RenderPassList& original_pass_list =
424 original_frame->delegated_frame_data->render_pass_list;
425 ASSERT_EQ(2u, original_pass_list.size());
426 DCHECK(original_pass_list[0]->copy_requests.empty());
427 DCHECK(original_pass_list[1]->copy_requests.empty());
429 factory_.Destroy(embedded_surface_id);
432 // This tests referencing a surface that has multiple render passes.
433 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
434 SurfaceId embedded_surface_id = child_allocator_.GenerateId();
435 factory_.Create(embedded_surface_id, SurfaceSize());
437 RenderPassId pass_ids[] = {RenderPassId(1, 1), RenderPassId(1, 2),
438 RenderPassId(1, 3)};
440 test::Quad embedded_quads[][2] = {
441 {test::Quad::SolidColorQuad(1), test::Quad::SolidColorQuad(2)},
442 {test::Quad::SolidColorQuad(3), test::Quad::RenderPassQuad(pass_ids[0])},
443 {test::Quad::SolidColorQuad(4), test::Quad::RenderPassQuad(pass_ids[1])}};
444 test::Pass embedded_passes[] = {
445 test::Pass(embedded_quads[0], arraysize(embedded_quads[0]), pass_ids[0]),
446 test::Pass(embedded_quads[1], arraysize(embedded_quads[1]), pass_ids[1]),
447 test::Pass(embedded_quads[2], arraysize(embedded_quads[2]), pass_ids[2])};
449 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
451 test::Quad root_quads[][2] = {
452 {test::Quad::SolidColorQuad(5), test::Quad::SolidColorQuad(6)},
453 {test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
454 test::Quad::RenderPassQuad(pass_ids[0])},
455 {test::Quad::SolidColorQuad(7), test::Quad::RenderPassQuad(pass_ids[1])}};
456 test::Pass root_passes[] = {
457 test::Pass(root_quads[0], arraysize(root_quads[0]), pass_ids[0]),
458 test::Pass(root_quads[1], arraysize(root_quads[1]), pass_ids[1]),
459 test::Pass(root_quads[2], arraysize(root_quads[2]), pass_ids[2])};
461 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
463 scoped_ptr<CompositorFrame> aggregated_frame =
464 aggregator_.Aggregate(root_surface_id_);
466 ASSERT_TRUE(aggregated_frame);
467 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
469 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
471 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
473 ASSERT_EQ(5u, aggregated_pass_list.size());
474 RenderPassId actual_pass_ids[] = {
475 aggregated_pass_list[0]->id, aggregated_pass_list[1]->id,
476 aggregated_pass_list[2]->id, aggregated_pass_list[3]->id,
477 aggregated_pass_list[4]->id};
478 for (size_t i = 0; i < 5; ++i) {
479 for (size_t j = 0; j < i; ++j) {
480 EXPECT_NE(actual_pass_ids[i], actual_pass_ids[j]);
485 SCOPED_TRACE("First pass");
486 // The first pass will just be the first pass from the root surfaces quad
487 // with no render pass quads to remap.
488 TestPassMatchesExpectations(root_passes[0], aggregated_pass_list[0]);
492 SCOPED_TRACE("Second pass");
493 // The next two passes will be from the embedded surface since we have to
494 // draw those passes before they are referenced from the render pass draw
495 // quad embedded into the root surface's second pass.
496 // First, there's the first embedded pass which doesn't reference anything
497 // else.
498 TestPassMatchesExpectations(embedded_passes[0], aggregated_pass_list[1]);
502 SCOPED_TRACE("Third pass");
503 const QuadList& third_pass_quad_list = aggregated_pass_list[2]->quad_list;
504 ASSERT_EQ(2u, third_pass_quad_list.size());
505 TestQuadMatchesExpectations(embedded_quads[1][0],
506 third_pass_quad_list.ElementAt(0));
508 // This render pass pass quad will reference the first pass from the
509 // embedded surface, which is the second pass in the aggregated frame.
510 ASSERT_EQ(DrawQuad::RENDER_PASS,
511 third_pass_quad_list.ElementAt(1)->material);
512 const RenderPassDrawQuad* third_pass_render_pass_draw_quad =
513 RenderPassDrawQuad::MaterialCast(third_pass_quad_list.ElementAt(1));
514 EXPECT_EQ(actual_pass_ids[1],
515 third_pass_render_pass_draw_quad->render_pass_id);
519 SCOPED_TRACE("Fourth pass");
520 // The fourth pass will have aggregated quads from the root surface's second
521 // pass and the embedded surface's first pass.
522 const QuadList& fourth_pass_quad_list = aggregated_pass_list[3]->quad_list;
523 ASSERT_EQ(3u, fourth_pass_quad_list.size());
525 // The first quad will be the yellow quad from the embedded surface's last
526 // pass.
527 TestQuadMatchesExpectations(embedded_quads[2][0],
528 fourth_pass_quad_list.ElementAt(0));
530 // The next quad will be a render pass quad referencing the second pass from
531 // the embedded surface, which is the third pass in the aggregated frame.
532 ASSERT_EQ(DrawQuad::RENDER_PASS,
533 fourth_pass_quad_list.ElementAt(1)->material);
534 const RenderPassDrawQuad* fourth_pass_first_render_pass_draw_quad =
535 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.ElementAt(1));
536 EXPECT_EQ(actual_pass_ids[2],
537 fourth_pass_first_render_pass_draw_quad->render_pass_id);
539 // The last quad will be a render pass quad referencing the first pass from
540 // the root surface, which is the first pass overall.
541 ASSERT_EQ(DrawQuad::RENDER_PASS,
542 fourth_pass_quad_list.ElementAt(2)->material);
543 const RenderPassDrawQuad* fourth_pass_second_render_pass_draw_quad =
544 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.ElementAt(2));
545 EXPECT_EQ(actual_pass_ids[0],
546 fourth_pass_second_render_pass_draw_quad->render_pass_id);
550 SCOPED_TRACE("Fifth pass");
551 const QuadList& fifth_pass_quad_list = aggregated_pass_list[4]->quad_list;
552 ASSERT_EQ(2u, fifth_pass_quad_list.size());
554 TestQuadMatchesExpectations(root_quads[2][0],
555 fifth_pass_quad_list.ElementAt(0));
557 // The last quad in the last pass will reference the second pass from the
558 // root surface, which after aggregating is the fourth pass in the overall
559 // list.
560 ASSERT_EQ(DrawQuad::RENDER_PASS,
561 fifth_pass_quad_list.ElementAt(1)->material);
562 const RenderPassDrawQuad* fifth_pass_render_pass_draw_quad =
563 RenderPassDrawQuad::MaterialCast(fifth_pass_quad_list.ElementAt(1));
564 EXPECT_EQ(actual_pass_ids[3],
565 fifth_pass_render_pass_draw_quad->render_pass_id);
567 factory_.Destroy(embedded_surface_id);
570 // Tests an invalid surface reference in a frame. The surface quad should just
571 // be dropped.
572 TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {
573 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
574 test::Quad::SurfaceQuad(InvalidSurfaceId(), 1.f),
575 test::Quad::SolidColorQuad(SK_ColorBLUE)};
576 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
578 SubmitFrame(passes, arraysize(passes), root_surface_id_);
580 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
581 test::Quad::SolidColorQuad(SK_ColorBLUE)};
582 test::Pass expected_passes[] = {
583 test::Pass(expected_quads, arraysize(expected_quads))};
584 SurfaceId ids[] = {root_surface_id_, InvalidSurfaceId()};
585 AggregateAndVerify(
586 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
589 // Tests a reference to a valid surface with no submitted frame. This quad
590 // should also just be dropped.
591 TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) {
592 SurfaceId surface_with_no_frame_id = allocator_.GenerateId();
593 factory_.Create(surface_with_no_frame_id, gfx::Size(5, 5));
594 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
595 test::Quad::SurfaceQuad(surface_with_no_frame_id, 1.f),
596 test::Quad::SolidColorQuad(SK_ColorBLUE)};
597 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
599 SubmitFrame(passes, arraysize(passes), root_surface_id_);
601 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
602 test::Quad::SolidColorQuad(SK_ColorBLUE)};
603 test::Pass expected_passes[] = {
604 test::Pass(expected_quads, arraysize(expected_quads))};
605 SurfaceId ids[] = {root_surface_id_, surface_with_no_frame_id};
606 AggregateAndVerify(
607 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
608 factory_.Destroy(surface_with_no_frame_id);
611 // Tests a surface quad referencing itself, generating a trivial cycle.
612 // The quad creating the cycle should be dropped from the final frame.
613 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {
614 test::Quad quads[] = {test::Quad::SurfaceQuad(root_surface_id_, 1.f),
615 test::Quad::SolidColorQuad(SK_ColorYELLOW)};
616 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
618 SubmitFrame(passes, arraysize(passes), root_surface_id_);
620 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorYELLOW)};
621 test::Pass expected_passes[] = {
622 test::Pass(expected_quads, arraysize(expected_quads))};
623 SurfaceId ids[] = {root_surface_id_};
624 AggregateAndVerify(
625 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
628 // Tests a more complex cycle with one intermediate surface.
629 TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
630 SurfaceId child_surface_id = allocator_.GenerateId();
631 factory_.Create(child_surface_id, SurfaceSize());
633 test::Quad parent_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
634 test::Quad::SurfaceQuad(child_surface_id, 1.f),
635 test::Quad::SolidColorQuad(SK_ColorCYAN)};
636 test::Pass parent_passes[] = {
637 test::Pass(parent_quads, arraysize(parent_quads))};
639 SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
641 test::Quad child_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
642 test::Quad::SurfaceQuad(root_surface_id_, 1.f),
643 test::Quad::SolidColorQuad(SK_ColorMAGENTA)};
644 test::Pass child_passes[] = {test::Pass(child_quads, arraysize(child_quads))};
646 SubmitFrame(child_passes, arraysize(child_passes), child_surface_id);
648 // The child surface's reference to the root_surface_ will be dropped, so
649 // we'll end up with:
650 // SK_ColorBLUE from the parent
651 // SK_ColorGREEN from the child
652 // SK_ColorMAGENTA from the child
653 // SK_ColorCYAN from the parent
654 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
655 test::Quad::SolidColorQuad(SK_ColorGREEN),
656 test::Quad::SolidColorQuad(SK_ColorMAGENTA),
657 test::Quad::SolidColorQuad(SK_ColorCYAN)};
658 test::Pass expected_passes[] = {
659 test::Pass(expected_quads, arraysize(expected_quads))};
660 SurfaceId ids[] = {root_surface_id_, child_surface_id};
661 AggregateAndVerify(
662 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
663 factory_.Destroy(child_surface_id);
666 // Tests that we map render pass IDs from different surfaces into a unified
667 // namespace and update RenderPassDrawQuad's id references to match.
668 TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
669 SurfaceId child_surface_id = allocator_.GenerateId();
670 factory_.Create(child_surface_id, SurfaceSize());
672 RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
673 test::Quad child_quad[][1] = {{test::Quad::SolidColorQuad(SK_ColorGREEN)},
674 {test::Quad::RenderPassQuad(child_pass_id[0])}};
675 test::Pass surface_passes[] = {
676 test::Pass(child_quad[0], arraysize(child_quad[0]), child_pass_id[0]),
677 test::Pass(child_quad[1], arraysize(child_quad[1]), child_pass_id[1])};
679 SubmitFrame(surface_passes, arraysize(surface_passes), child_surface_id);
681 // Pass IDs from the parent surface may collide with ones from the child.
682 RenderPassId parent_pass_id[] = {RenderPassId(2, 1), RenderPassId(1, 2)};
683 test::Quad parent_quad[][1] = {
684 {test::Quad::SurfaceQuad(child_surface_id, 1.f)},
685 {test::Quad::RenderPassQuad(parent_pass_id[0])}};
686 test::Pass parent_passes[] = {
687 test::Pass(parent_quad[0], arraysize(parent_quad[0]), parent_pass_id[0]),
688 test::Pass(parent_quad[1], arraysize(parent_quad[1]), parent_pass_id[1])};
690 SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
691 scoped_ptr<CompositorFrame> aggregated_frame =
692 aggregator_.Aggregate(root_surface_id_);
694 ASSERT_TRUE(aggregated_frame);
695 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
697 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
699 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
701 ASSERT_EQ(3u, aggregated_pass_list.size());
702 RenderPassId actual_pass_ids[] = {aggregated_pass_list[0]->id,
703 aggregated_pass_list[1]->id,
704 aggregated_pass_list[2]->id};
705 // Make sure the aggregated frame's pass IDs are all unique.
706 for (size_t i = 0; i < 3; ++i) {
707 for (size_t j = 0; j < i; ++j) {
708 EXPECT_NE(actual_pass_ids[j], actual_pass_ids[i]) << "pass ids " << i
709 << " and " << j;
713 // Make sure the render pass quads reference the remapped pass IDs.
714 DrawQuad* render_pass_quads[] = {aggregated_pass_list[1]->quad_list.front(),
715 aggregated_pass_list[2]->quad_list.front()};
716 ASSERT_EQ(render_pass_quads[0]->material, DrawQuad::RENDER_PASS);
717 EXPECT_EQ(
718 actual_pass_ids[0],
719 RenderPassDrawQuad::MaterialCast(render_pass_quads[0])->render_pass_id);
721 ASSERT_EQ(render_pass_quads[1]->material, DrawQuad::RENDER_PASS);
722 EXPECT_EQ(
723 actual_pass_ids[1],
724 RenderPassDrawQuad::MaterialCast(render_pass_quads[1])->render_pass_id);
725 factory_.Destroy(child_surface_id);
728 void AddSolidColorQuadWithBlendMode(const gfx::Size& size,
729 RenderPass* pass,
730 const SkXfermode::Mode blend_mode) {
731 const gfx::Transform content_to_target_transform;
732 const gfx::Size content_bounds(size);
733 const gfx::Rect visible_content_rect(size);
734 const gfx::Rect clip_rect(size);
736 bool is_clipped = false;
737 float opacity = 1.f;
739 bool force_anti_aliasing_off = false;
740 SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
741 sqs->SetAll(content_to_target_transform,
742 content_bounds,
743 visible_content_rect,
744 clip_rect,
745 is_clipped,
746 opacity,
747 blend_mode,
750 SolidColorDrawQuad* color_quad =
751 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
752 color_quad->SetNew(pass->shared_quad_state_list.back(),
753 visible_content_rect,
754 visible_content_rect,
755 SK_ColorGREEN,
756 force_anti_aliasing_off);
759 // This tests that we update shared quad state pointers correctly within
760 // aggregated passes. The shared quad state list on the aggregated pass will
761 // include the shared quad states from each pass in one list so the quads will
762 // end up pointed to shared quad state objects at different offsets. This test
763 // uses the blend_mode value stored on the shared quad state to track the shared
764 // quad state, but anything saved on the shared quad state would work.
766 // This test has 4 surfaces in the following structure:
767 // root_surface -> quad with kClear_Mode,
768 // [child_one_surface],
769 // quad with kDstOver_Mode,
770 // [child_two_surface],
771 // quad with kDstIn_Mode
772 // child_one_surface -> quad with kSrc_Mode,
773 // [grandchild_surface],
774 // quad with kSrcOver_Mode
775 // child_two_surface -> quad with kSrcIn_Mode
776 // grandchild_surface -> quad with kDst_Mode
778 // Resulting in the following aggregated pass:
779 // quad_root_0 - blend_mode kClear_Mode
780 // quad_child_one_0 - blend_mode kSrc_Mode
781 // quad_grandchild_0 - blend_mode kDst_Mode
782 // quad_child_one_1 - blend_mode kSrcOver_Mode
783 // quad_root_1 - blend_mode kDstOver_Mode
784 // quad_child_two_0 - blend_mode kSrcIn_Mode
785 // quad_root_2 - blend_mode kDstIn_Mode
786 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
787 const SkXfermode::Mode blend_modes[] = {SkXfermode::kClear_Mode, // 0
788 SkXfermode::kSrc_Mode, // 1
789 SkXfermode::kDst_Mode, // 2
790 SkXfermode::kSrcOver_Mode, // 3
791 SkXfermode::kDstOver_Mode, // 4
792 SkXfermode::kSrcIn_Mode, // 5
793 SkXfermode::kDstIn_Mode, // 6
796 RenderPassId pass_id(1, 1);
797 SurfaceId grandchild_surface_id = allocator_.GenerateId();
798 factory_.Create(grandchild_surface_id, SurfaceSize());
799 scoped_ptr<RenderPass> grandchild_pass = RenderPass::Create();
800 gfx::Rect output_rect(SurfaceSize());
801 gfx::Rect damage_rect(SurfaceSize());
802 gfx::Transform transform_to_root_target;
803 grandchild_pass->SetNew(
804 pass_id, output_rect, damage_rect, transform_to_root_target);
805 AddSolidColorQuadWithBlendMode(
806 SurfaceSize(), grandchild_pass.get(), blend_modes[2]);
807 QueuePassAsFrame(grandchild_pass.Pass(), grandchild_surface_id);
809 SurfaceId child_one_surface_id = allocator_.GenerateId();
810 factory_.Create(child_one_surface_id, SurfaceSize());
812 scoped_ptr<RenderPass> child_one_pass = RenderPass::Create();
813 child_one_pass->SetNew(
814 pass_id, output_rect, damage_rect, transform_to_root_target);
815 AddSolidColorQuadWithBlendMode(
816 SurfaceSize(), child_one_pass.get(), blend_modes[1]);
817 SurfaceDrawQuad* grandchild_surface_quad =
818 child_one_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
819 grandchild_surface_quad->SetNew(child_one_pass->shared_quad_state_list.back(),
820 gfx::Rect(SurfaceSize()),
821 gfx::Rect(SurfaceSize()),
822 grandchild_surface_id);
823 AddSolidColorQuadWithBlendMode(
824 SurfaceSize(), child_one_pass.get(), blend_modes[3]);
825 QueuePassAsFrame(child_one_pass.Pass(), child_one_surface_id);
827 SurfaceId child_two_surface_id = allocator_.GenerateId();
828 factory_.Create(child_two_surface_id, SurfaceSize());
830 scoped_ptr<RenderPass> child_two_pass = RenderPass::Create();
831 child_two_pass->SetNew(
832 pass_id, output_rect, damage_rect, transform_to_root_target);
833 AddSolidColorQuadWithBlendMode(
834 SurfaceSize(), child_two_pass.get(), blend_modes[5]);
835 QueuePassAsFrame(child_two_pass.Pass(), child_two_surface_id);
837 scoped_ptr<RenderPass> root_pass = RenderPass::Create();
838 root_pass->SetNew(
839 pass_id, output_rect, damage_rect, transform_to_root_target);
841 AddSolidColorQuadWithBlendMode(
842 SurfaceSize(), root_pass.get(), blend_modes[0]);
843 SurfaceDrawQuad* child_one_surface_quad =
844 root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
845 child_one_surface_quad->SetNew(root_pass->shared_quad_state_list.back(),
846 gfx::Rect(SurfaceSize()),
847 gfx::Rect(SurfaceSize()),
848 child_one_surface_id);
849 AddSolidColorQuadWithBlendMode(
850 SurfaceSize(), root_pass.get(), blend_modes[4]);
851 SurfaceDrawQuad* child_two_surface_quad =
852 root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
853 child_two_surface_quad->SetNew(root_pass->shared_quad_state_list.back(),
854 gfx::Rect(SurfaceSize()),
855 gfx::Rect(SurfaceSize()),
856 child_two_surface_id);
857 AddSolidColorQuadWithBlendMode(
858 SurfaceSize(), root_pass.get(), blend_modes[6]);
860 QueuePassAsFrame(root_pass.Pass(), root_surface_id_);
862 scoped_ptr<CompositorFrame> aggregated_frame =
863 aggregator_.Aggregate(root_surface_id_);
865 ASSERT_TRUE(aggregated_frame);
866 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
868 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
870 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
872 ASSERT_EQ(1u, aggregated_pass_list.size());
874 const QuadList& aggregated_quad_list = aggregated_pass_list[0]->quad_list;
876 ASSERT_EQ(7u, aggregated_quad_list.size());
878 for (auto iter = aggregated_quad_list.cbegin();
879 iter != aggregated_quad_list.cend();
880 ++iter) {
881 EXPECT_EQ(blend_modes[iter.index()], iter->shared_quad_state->blend_mode)
882 << iter.index();
884 factory_.Destroy(child_one_surface_id);
885 factory_.Destroy(child_two_surface_id);
886 factory_.Destroy(grandchild_surface_id);
889 // This tests that when aggregating a frame with multiple render passes that we
890 // map the transforms for the root pass but do not modify the transform on child
891 // passes.
893 // The root surface has one pass with a surface quad transformed by +10 in the y
894 // direction.
896 // The child surface has two passes. The first pass has a quad with a transform
897 // of +5 in the x direction. The second pass has a reference to the first pass'
898 // pass id and a transform of +8 in the x direction.
900 // After aggregation, the child surface's root pass quad should have both
901 // transforms concatenated for a total transform of +8 x, +10 y. The
902 // contributing render pass' transform in the aggregate frame should not be
903 // affected.
904 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
905 SurfaceId child_surface_id = allocator_.GenerateId();
906 factory_.Create(child_surface_id, SurfaceSize());
907 RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
908 test::Quad child_quads[][1] = {
909 {test::Quad::SolidColorQuad(SK_ColorGREEN)},
910 {test::Quad::RenderPassQuad(child_pass_id[0])}};
911 test::Pass child_passes[] = {
912 test::Pass(child_quads[0], arraysize(child_quads[0]), child_pass_id[0]),
913 test::Pass(child_quads[1], arraysize(child_quads[1]), child_pass_id[1])};
915 RenderPassList child_pass_list;
916 AddPasses(&child_pass_list,
917 gfx::Rect(SurfaceSize()),
918 child_passes,
919 arraysize(child_passes));
921 RenderPass* child_nonroot_pass = child_pass_list.at(0u);
922 child_nonroot_pass->transform_to_root_target.Translate(8, 0);
923 SharedQuadState* child_nonroot_pass_sqs =
924 child_nonroot_pass->shared_quad_state_list.front();
925 child_nonroot_pass_sqs->content_to_target_transform.Translate(5, 0);
927 RenderPass* child_root_pass = child_pass_list.at(1u);
928 SharedQuadState* child_root_pass_sqs =
929 child_root_pass->shared_quad_state_list.front();
930 child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
931 child_root_pass_sqs->is_clipped = true;
932 child_root_pass_sqs->clip_rect = gfx::Rect(0, 0, 5, 5);
934 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
935 child_pass_list.swap(child_frame_data->render_pass_list);
937 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
938 child_frame->delegated_frame_data = child_frame_data.Pass();
940 factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
942 test::Quad root_quads[] = {test::Quad::SolidColorQuad(1),
943 test::Quad::SurfaceQuad(child_surface_id, 1.f)};
944 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
946 RenderPassList root_pass_list;
947 AddPasses(&root_pass_list,
948 gfx::Rect(SurfaceSize()),
949 root_passes,
950 arraysize(root_passes));
952 root_pass_list.at(0)
953 ->shared_quad_state_list.front()
954 ->content_to_target_transform.Translate(0, 7);
955 root_pass_list.at(0)
956 ->shared_quad_state_list.ElementAt(1)
957 ->content_to_target_transform.Translate(0, 10);
959 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
960 root_pass_list.swap(root_frame_data->render_pass_list);
962 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
963 root_frame->delegated_frame_data = root_frame_data.Pass();
965 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
967 scoped_ptr<CompositorFrame> aggregated_frame =
968 aggregator_.Aggregate(root_surface_id_);
970 ASSERT_TRUE(aggregated_frame);
971 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
973 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
975 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
977 ASSERT_EQ(2u, aggregated_pass_list.size());
979 ASSERT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
981 // The first pass should have one shared quad state for the one solid color
982 // quad.
983 EXPECT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
984 // The second (root) pass should have just two shared quad states. We'll
985 // verify the properties through the quads.
986 EXPECT_EQ(2u, aggregated_pass_list[1]->shared_quad_state_list.size());
988 SharedQuadState* aggregated_first_pass_sqs =
989 aggregated_pass_list[0]->shared_quad_state_list.front();
991 // The first pass's transform should be unaffected by the embedding and still
992 // be a translation by +5 in the x direction.
993 gfx::Transform expected_aggregated_first_pass_sqs_transform;
994 expected_aggregated_first_pass_sqs_transform.Translate(5, 0);
995 EXPECT_EQ(expected_aggregated_first_pass_sqs_transform.ToString(),
996 aggregated_first_pass_sqs->content_to_target_transform.ToString());
998 // The first pass's transform to the root target should include the aggregated
999 // transform.
1000 gfx::Transform expected_first_pass_transform_to_root_target;
1001 expected_first_pass_transform_to_root_target.Translate(8, 10);
1002 EXPECT_EQ(expected_first_pass_transform_to_root_target.ToString(),
1003 aggregated_pass_list[0]->transform_to_root_target.ToString());
1005 ASSERT_EQ(2u, aggregated_pass_list[1]->quad_list.size());
1007 gfx::Transform expected_root_pass_quad_transforms[2];
1008 // The first quad in the root pass is the solid color quad from the original
1009 // root surface. Its transform should be unaffected by the aggregation and
1010 // still be +7 in the y direction.
1011 expected_root_pass_quad_transforms[0].Translate(0, 7);
1012 // The second quad in the root pass is aggregated from the child surface so
1013 // its transform should be the combination of its original translation (0, 10)
1014 // and the child surface draw quad's translation (8, 0).
1015 expected_root_pass_quad_transforms[1].Translate(8, 10);
1017 for (auto iter = aggregated_pass_list[1]->quad_list.cbegin();
1018 iter != aggregated_pass_list[1]->quad_list.cend();
1019 ++iter) {
1020 EXPECT_EQ(expected_root_pass_quad_transforms[iter.index()].ToString(),
1021 iter->quadTransform().ToString())
1022 << iter.index();
1025 EXPECT_TRUE(
1026 aggregated_pass_list[1]->shared_quad_state_list.ElementAt(1)->is_clipped);
1028 // The second quad in the root pass is aggregated from the child, so its
1029 // clip rect must be transformed by the child's translation.
1030 EXPECT_EQ(gfx::Rect(0, 10, 5, 5).ToString(),
1031 aggregated_pass_list[1]
1032 ->shared_quad_state_list.ElementAt(1)
1033 ->clip_rect.ToString());
1035 factory_.Destroy(child_surface_id);
1038 // Tests that damage rects are aggregated correctly when surfaces change.
1039 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
1040 SurfaceId child_surface_id = allocator_.GenerateId();
1041 factory_.Create(child_surface_id, SurfaceSize());
1042 RenderPassId child_pass_id = RenderPassId(1, 1);
1043 test::Quad child_quads[] = {test::Quad::RenderPassQuad(child_pass_id)};
1044 test::Pass child_passes[] = {
1045 test::Pass(child_quads, arraysize(child_quads), child_pass_id)};
1047 RenderPassList child_pass_list;
1048 AddPasses(&child_pass_list,
1049 gfx::Rect(SurfaceSize()),
1050 child_passes,
1051 arraysize(child_passes));
1053 RenderPass* child_root_pass = child_pass_list.at(0u);
1054 SharedQuadState* child_root_pass_sqs =
1055 child_root_pass->shared_quad_state_list.front();
1056 child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
1058 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
1059 child_pass_list.swap(child_frame_data->render_pass_list);
1061 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
1062 child_frame->delegated_frame_data = child_frame_data.Pass();
1064 factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
1066 test::Quad root_quads[] = {test::Quad::SurfaceQuad(child_surface_id, 1.f)};
1067 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
1069 RenderPassList root_pass_list;
1070 AddPasses(&root_pass_list,
1071 gfx::Rect(SurfaceSize()),
1072 root_passes,
1073 arraysize(root_passes));
1075 root_pass_list.at(0)
1076 ->shared_quad_state_list.front()
1077 ->content_to_target_transform.Translate(0, 10);
1078 root_pass_list.at(0)->damage_rect = gfx::Rect(5, 5, 10, 10);
1080 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1081 root_pass_list.swap(root_frame_data->render_pass_list);
1083 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1084 root_frame->delegated_frame_data = root_frame_data.Pass();
1086 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
1088 scoped_ptr<CompositorFrame> aggregated_frame =
1089 aggregator_.Aggregate(root_surface_id_);
1091 ASSERT_TRUE(aggregated_frame);
1092 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1094 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
1096 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1098 ASSERT_EQ(1u, aggregated_pass_list.size());
1100 // Damage rect for first aggregation should contain entire root surface.
1101 EXPECT_TRUE(
1102 aggregated_pass_list[0]->damage_rect.Contains(gfx::Rect(SurfaceSize())));
1105 AddPasses(&child_pass_list,
1106 gfx::Rect(SurfaceSize()),
1107 child_passes,
1108 arraysize(child_passes));
1110 RenderPass* child_root_pass = child_pass_list.at(0u);
1111 SharedQuadState* child_root_pass_sqs =
1112 child_root_pass->shared_quad_state_list.front();
1113 child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
1114 child_root_pass->damage_rect = gfx::Rect(10, 10, 10, 10);
1116 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
1117 child_pass_list.swap(child_frame_data->render_pass_list);
1119 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
1120 child_frame->delegated_frame_data = child_frame_data.Pass();
1122 factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
1124 scoped_ptr<CompositorFrame> aggregated_frame =
1125 aggregator_.Aggregate(root_surface_id_);
1127 ASSERT_TRUE(aggregated_frame);
1128 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1130 DelegatedFrameData* frame_data =
1131 aggregated_frame->delegated_frame_data.get();
1133 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1135 ASSERT_EQ(1u, aggregated_pass_list.size());
1137 // Outer surface didn't change, so transformed inner damage rect should be
1138 // used.
1139 EXPECT_EQ(gfx::Rect(10, 20, 10, 10).ToString(),
1140 aggregated_pass_list[0]->damage_rect.ToString());
1144 RenderPassList root_pass_list;
1145 AddPasses(&root_pass_list,
1146 gfx::Rect(SurfaceSize()),
1147 root_passes,
1148 arraysize(root_passes));
1150 root_pass_list.at(0)
1151 ->shared_quad_state_list.front()
1152 ->content_to_target_transform.Translate(0, 10);
1153 root_pass_list.at(0)->damage_rect = gfx::Rect(0, 0, 1, 1);
1155 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1156 root_pass_list.swap(root_frame_data->render_pass_list);
1158 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1159 root_frame->delegated_frame_data = root_frame_data.Pass();
1161 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
1165 RenderPassList root_pass_list;
1166 AddPasses(&root_pass_list,
1167 gfx::Rect(SurfaceSize()),
1168 root_passes,
1169 arraysize(root_passes));
1171 root_pass_list.at(0)
1172 ->shared_quad_state_list.front()
1173 ->content_to_target_transform.Translate(0, 10);
1174 root_pass_list.at(0)->damage_rect = gfx::Rect(1, 1, 1, 1);
1176 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1177 root_pass_list.swap(root_frame_data->render_pass_list);
1179 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1180 root_frame->delegated_frame_data = root_frame_data.Pass();
1182 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
1184 scoped_ptr<CompositorFrame> aggregated_frame =
1185 aggregator_.Aggregate(root_surface_id_);
1187 ASSERT_TRUE(aggregated_frame);
1188 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1190 DelegatedFrameData* frame_data =
1191 aggregated_frame->delegated_frame_data.get();
1193 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1195 ASSERT_EQ(1u, aggregated_pass_list.size());
1197 // The root surface was enqueued without being aggregated once, so it should
1198 // be treated as completely damaged.
1199 EXPECT_TRUE(aggregated_pass_list[0]->damage_rect.Contains(
1200 gfx::Rect(SurfaceSize())));
1203 factory_.Destroy(child_surface_id);
1206 class SurfaceAggregatorWithResourcesTest : public testing::Test {
1207 public:
1208 virtual void SetUp() {
1209 output_surface_ = FakeOutputSurface::CreateSoftware(
1210 make_scoped_ptr(new SoftwareOutputDevice));
1211 output_surface_->BindToClient(&output_surface_client_);
1212 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
1214 resource_provider_ = ResourceProvider::Create(output_surface_.get(),
1215 shared_bitmap_manager_.get(),
1216 NULL,
1217 NULL,
1219 false,
1222 aggregator_.reset(
1223 new SurfaceAggregator(&manager_, resource_provider_.get()));
1226 protected:
1227 SurfaceManager manager_;
1228 FakeOutputSurfaceClient output_surface_client_;
1229 scoped_ptr<OutputSurface> output_surface_;
1230 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
1231 scoped_ptr<ResourceProvider> resource_provider_;
1232 scoped_ptr<SurfaceAggregator> aggregator_;
1235 class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient {
1236 public:
1237 ResourceTrackingSurfaceFactoryClient() {}
1238 ~ResourceTrackingSurfaceFactoryClient() override {}
1240 void ReturnResources(const ReturnedResourceArray& resources) override {
1241 returned_resources_ = resources;
1244 ReturnedResourceArray returned_resources() const {
1245 return returned_resources_;
1248 private:
1249 ReturnedResourceArray returned_resources_;
1251 DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient);
1254 void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids,
1255 size_t num_resource_ids,
1256 SurfaceFactory* factory,
1257 SurfaceId surface_id) {
1258 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
1259 scoped_ptr<RenderPass> pass = RenderPass::Create();
1260 pass->id = RenderPassId(1, 1);
1261 SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
1262 for (size_t i = 0u; i < num_resource_ids; ++i) {
1263 TransferableResource resource;
1264 resource.id = resource_ids[i];
1265 resource.is_software = true;
1266 frame_data->resource_list.push_back(resource);
1267 TextureDrawQuad* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
1268 const gfx::Rect rect;
1269 const gfx::Rect opaque_rect;
1270 const gfx::Rect visible_rect;
1271 bool needs_blending = false;
1272 bool premultiplied_alpha = false;
1273 const gfx::PointF uv_top_left;
1274 const gfx::PointF uv_bottom_right;
1275 SkColor background_color = SK_ColorGREEN;
1276 const float vertex_opacity[4] = {0.f, 0.f, 1.f, 1.f};
1277 bool flipped = false;
1278 quad->SetAll(sqs,
1279 rect,
1280 opaque_rect,
1281 visible_rect,
1282 needs_blending,
1283 resource_ids[i],
1284 premultiplied_alpha,
1285 uv_top_left,
1286 uv_bottom_right,
1287 background_color,
1288 vertex_opacity,
1289 flipped);
1291 quad->shared_quad_state = sqs;
1293 frame_data->render_pass_list.push_back(pass.Pass());
1294 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
1295 frame->delegated_frame_data = frame_data.Pass();
1296 factory->SubmitFrame(surface_id, frame.Pass(), base::Closure());
1299 TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
1300 ResourceTrackingSurfaceFactoryClient client;
1301 SurfaceFactory factory(&manager_, &client);
1302 SurfaceId surface_id(7u);
1303 factory.Create(surface_id, SurfaceSize());
1305 ResourceProvider::ResourceId ids[] = {11, 12, 13};
1306 SubmitFrameWithResources(ids, arraysize(ids), &factory, surface_id);
1308 scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id);
1310 // Nothing should be available to be returned yet.
1311 EXPECT_TRUE(client.returned_resources().empty());
1313 SubmitFrameWithResources(NULL, 0u, &factory, surface_id);
1315 frame = aggregator_->Aggregate(surface_id);
1317 ASSERT_EQ(3u, client.returned_resources().size());
1318 ResourceProvider::ResourceId returned_ids[3];
1319 for (size_t i = 0; i < 3; ++i) {
1320 returned_ids[i] = client.returned_resources()[i].id;
1322 EXPECT_THAT(returned_ids,
1323 testing::WhenSorted(testing::ElementsAreArray(ids)));
1324 factory.Destroy(surface_id);
1327 TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) {
1328 ResourceTrackingSurfaceFactoryClient client;
1329 SurfaceFactory factory(&manager_, &client);
1330 SurfaceId surface_id(7u);
1331 factory.Create(surface_id, SurfaceSize());
1332 SurfaceId surface_id2(8u);
1333 factory.Create(surface_id2, SurfaceSize());
1335 ResourceProvider::ResourceId ids[] = {11, 12, 13};
1336 SubmitFrameWithResources(ids, arraysize(ids), &factory, surface_id);
1337 ResourceProvider::ResourceId ids2[] = {14, 15, 16};
1338 SubmitFrameWithResources(ids2, arraysize(ids2), &factory, surface_id2);
1340 scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id);
1342 SubmitFrameWithResources(NULL, 0, &factory, surface_id);
1344 // Nothing should be available to be returned yet.
1345 EXPECT_TRUE(client.returned_resources().empty());
1347 frame = aggregator_->Aggregate(surface_id2);
1349 // surface_id wasn't referenced, so its resources should be returned.
1350 ASSERT_EQ(3u, client.returned_resources().size());
1351 ResourceProvider::ResourceId returned_ids[3];
1352 for (size_t i = 0; i < 3; ++i) {
1353 returned_ids[i] = client.returned_resources()[i].id;
1355 EXPECT_THAT(returned_ids,
1356 testing::WhenSorted(testing::ElementsAreArray(ids)));
1357 EXPECT_EQ(3u, resource_provider_->num_resources());
1358 factory.Destroy(surface_id);
1359 factory.Destroy(surface_id2);
1362 } // namespace
1363 } // namespace cc