Update EnsureProcessGetsReaped to receive a pid.
[chromium-blink-merge.git] / cc / surfaces / surface_aggregator_unittest.cc
blob1dff7ec2c22bce2cecdf0d7631a35d12737fe0a2
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);
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 void SetUp() override {
73 SurfaceAggregatorTest::SetUp();
74 root_surface_id_ = allocator_.GenerateId();
75 factory_.Create(root_surface_id_);
78 void TearDown() override {
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(),
127 SurfaceFactory::DrawCallback());
130 void QueuePassAsFrame(scoped_ptr<RenderPass> pass, SurfaceId surface_id) {
131 scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
132 delegated_frame_data->render_pass_list.push_back(pass.Pass());
134 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
135 child_frame->delegated_frame_data = delegated_frame_data.Pass();
137 factory_.SubmitFrame(surface_id, child_frame.Pass(),
138 SurfaceFactory::DrawCallback());
141 protected:
142 SurfaceId root_surface_id_;
143 SurfaceIdAllocator allocator_;
144 SurfaceIdAllocator child_allocator_;
147 // Tests that a very simple frame containing only two solid color quads makes it
148 // through the aggregator correctly.
149 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) {
150 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorRED),
151 test::Quad::SolidColorQuad(SK_ColorBLUE)};
152 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
154 SubmitFrame(passes, arraysize(passes), root_surface_id_);
156 SurfaceId ids[] = {root_surface_id_};
157 AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids));
160 TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {
161 SurfaceId embedded_surface_id = allocator_.GenerateId();
162 factory_.Create(embedded_surface_id);
164 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
165 test::Quad::SolidColorQuad(SK_ColorBLUE)};
166 test::Pass embedded_passes[] = {
167 test::Pass(embedded_quads, arraysize(embedded_quads))};
169 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
171 test::Quad quads[] = {test::Quad::SurfaceQuad(embedded_surface_id, .5f)};
172 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
174 SubmitFrame(passes, arraysize(passes), root_surface_id_);
176 scoped_ptr<CompositorFrame> aggregated_frame =
177 aggregator_.Aggregate(root_surface_id_);
179 ASSERT_TRUE(aggregated_frame);
180 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
182 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
184 RenderPassList& render_pass_list(frame_data->render_pass_list);
185 ASSERT_EQ(2u, render_pass_list.size());
186 SharedQuadStateList& shared_quad_state_list(
187 render_pass_list[0]->shared_quad_state_list);
188 ASSERT_EQ(2u, shared_quad_state_list.size());
189 EXPECT_EQ(1.f, shared_quad_state_list.ElementAt(0)->opacity);
190 EXPECT_EQ(1.f, shared_quad_state_list.ElementAt(1)->opacity);
192 SharedQuadStateList& shared_quad_state_list2(
193 render_pass_list[1]->shared_quad_state_list);
194 ASSERT_EQ(1u, shared_quad_state_list2.size());
195 EXPECT_EQ(.5f, shared_quad_state_list2.ElementAt(0)->opacity);
197 factory_.Destroy(embedded_surface_id);
200 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {
201 test::Quad quads[][2] = {{test::Quad::SolidColorQuad(SK_ColorWHITE),
202 test::Quad::SolidColorQuad(SK_ColorLTGRAY)},
203 {test::Quad::SolidColorQuad(SK_ColorGRAY),
204 test::Quad::SolidColorQuad(SK_ColorDKGRAY)}};
205 test::Pass passes[] = {
206 test::Pass(quads[0], arraysize(quads[0]), RenderPassId(1, 1)),
207 test::Pass(quads[1], arraysize(quads[1]), RenderPassId(1, 2))};
209 SubmitFrame(passes, arraysize(passes), root_surface_id_);
211 SurfaceId ids[] = {root_surface_id_};
212 AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids));
215 // This tests very simple embedding. root_surface has a frame containing a few
216 // solid color quads and a surface quad referencing embedded_surface.
217 // embedded_surface has a frame containing only a solid color quad. The solid
218 // color quad should be aggregated into the final frame.
219 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
220 SurfaceId embedded_surface_id = allocator_.GenerateId();
221 factory_.Create(embedded_surface_id);
223 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
224 test::Pass embedded_passes[] = {
225 test::Pass(embedded_quads, arraysize(embedded_quads))};
227 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
229 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
230 test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
231 test::Quad::SolidColorQuad(SK_ColorBLACK)};
232 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
234 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
236 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
237 test::Quad::SolidColorQuad(SK_ColorGREEN),
238 test::Quad::SolidColorQuad(SK_ColorBLACK)};
239 test::Pass expected_passes[] = {
240 test::Pass(expected_quads, arraysize(expected_quads))};
241 SurfaceId ids[] = {root_surface_id_, embedded_surface_id};
242 AggregateAndVerify(
243 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
245 factory_.Destroy(embedded_surface_id);
248 TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
249 SurfaceId embedded_surface_id = allocator_.GenerateId();
250 factory_.Create(embedded_surface_id);
252 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
253 test::Pass embedded_passes[] = {
254 test::Pass(embedded_quads, arraysize(embedded_quads))};
256 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
257 scoped_ptr<CopyOutputRequest> copy_request(
258 CopyOutputRequest::CreateEmptyRequest());
259 CopyOutputRequest* copy_request_ptr = copy_request.get();
260 factory_.RequestCopyOfSurface(embedded_surface_id, copy_request.Pass());
262 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
263 test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
264 test::Quad::SolidColorQuad(SK_ColorBLACK)};
265 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
267 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
269 scoped_ptr<CompositorFrame> aggregated_frame =
270 aggregator_.Aggregate(root_surface_id_);
272 ASSERT_TRUE(aggregated_frame);
273 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
275 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
277 test::Quad expected_quads[] = {
278 test::Quad::SolidColorQuad(SK_ColorWHITE),
279 test::Quad::RenderPassQuad(frame_data->render_pass_list[0]->id),
280 test::Quad::SolidColorQuad(SK_ColorBLACK)};
281 test::Pass expected_passes[] = {
282 test::Pass(embedded_quads, arraysize(embedded_quads)),
283 test::Pass(expected_quads, arraysize(expected_quads))};
284 TestPassesMatchExpectations(expected_passes,
285 arraysize(expected_passes),
286 &frame_data->render_pass_list);
287 ASSERT_EQ(2u, frame_data->render_pass_list.size());
288 ASSERT_EQ(1u, frame_data->render_pass_list[0]->copy_requests.size());
289 DCHECK_EQ(copy_request_ptr,
290 frame_data->render_pass_list[0]->copy_requests[0]);
292 SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id};
293 EXPECT_EQ(arraysize(surface_ids),
294 aggregator_.previous_contained_surfaces().size());
295 for (size_t i = 0; i < arraysize(surface_ids); i++) {
296 EXPECT_TRUE(
297 aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
298 aggregator_.previous_contained_surfaces().end());
301 factory_.Destroy(embedded_surface_id);
304 // Root surface may contain copy requests.
305 TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
306 SurfaceId embedded_surface_id = allocator_.GenerateId();
307 factory_.Create(embedded_surface_id);
309 test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
310 test::Pass embedded_passes[] = {
311 test::Pass(embedded_quads, arraysize(embedded_quads))};
313 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
314 scoped_ptr<CopyOutputRequest> copy_request(
315 CopyOutputRequest::CreateEmptyRequest());
316 CopyOutputRequest* copy_request_ptr = copy_request.get();
317 scoped_ptr<CopyOutputRequest> copy_request2(
318 CopyOutputRequest::CreateEmptyRequest());
319 CopyOutputRequest* copy_request2_ptr = copy_request2.get();
321 test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
322 test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
323 test::Quad::SolidColorQuad(SK_ColorBLACK)};
324 test::Quad root_quads2[] = {test::Quad::SolidColorQuad(SK_ColorRED)};
325 test::Pass root_passes[] = {
326 test::Pass(root_quads, arraysize(root_quads), RenderPassId(1, 1)),
327 test::Pass(root_quads2, arraysize(root_quads2), RenderPassId(1, 2))};
329 RenderPassList pass_list;
330 AddPasses(&pass_list,
331 gfx::Rect(SurfaceSize()),
332 root_passes,
333 arraysize(root_passes));
334 pass_list[0]->copy_requests.push_back(copy_request.Pass());
335 pass_list[1]->copy_requests.push_back(copy_request2.Pass());
337 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
338 pass_list.swap(frame_data->render_pass_list);
340 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
341 frame->delegated_frame_data = frame_data.Pass();
343 factory_.SubmitFrame(root_surface_id_, frame.Pass(),
344 SurfaceFactory::DrawCallback());
347 scoped_ptr<CompositorFrame> aggregated_frame =
348 aggregator_.Aggregate(root_surface_id_);
350 ASSERT_TRUE(aggregated_frame);
351 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
353 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
355 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
356 test::Quad::SolidColorQuad(SK_ColorGREEN),
357 test::Quad::SolidColorQuad(SK_ColorBLACK)};
358 test::Pass expected_passes[] = {
359 test::Pass(expected_quads, arraysize(expected_quads)),
360 test::Pass(root_quads2, arraysize(root_quads2))};
361 TestPassesMatchExpectations(expected_passes,
362 arraysize(expected_passes),
363 &frame_data->render_pass_list);
364 ASSERT_EQ(2u, frame_data->render_pass_list.size());
365 ASSERT_EQ(1u, frame_data->render_pass_list[0]->copy_requests.size());
366 DCHECK_EQ(copy_request_ptr,
367 frame_data->render_pass_list[0]->copy_requests[0]);
368 ASSERT_EQ(1u, frame_data->render_pass_list[1]->copy_requests.size());
369 DCHECK_EQ(copy_request2_ptr,
370 frame_data->render_pass_list[1]->copy_requests[0]);
372 SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id};
373 EXPECT_EQ(arraysize(surface_ids),
374 aggregator_.previous_contained_surfaces().size());
375 for (size_t i = 0; i < arraysize(surface_ids); i++) {
376 EXPECT_TRUE(
377 aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
378 aggregator_.previous_contained_surfaces().end());
381 // Ensure copy requests have been removed from root surface.
382 const CompositorFrame* original_frame =
383 manager_.GetSurfaceForId(root_surface_id_)->GetEligibleFrame();
384 RenderPassList& original_pass_list =
385 original_frame->delegated_frame_data->render_pass_list;
386 ASSERT_EQ(2u, original_pass_list.size());
387 DCHECK(original_pass_list[0]->copy_requests.empty());
388 DCHECK(original_pass_list[1]->copy_requests.empty());
390 factory_.Destroy(embedded_surface_id);
393 // This tests referencing a surface that has multiple render passes.
394 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
395 SurfaceId embedded_surface_id = child_allocator_.GenerateId();
396 factory_.Create(embedded_surface_id);
398 RenderPassId pass_ids[] = {RenderPassId(1, 1), RenderPassId(1, 2),
399 RenderPassId(1, 3)};
401 test::Quad embedded_quads[][2] = {
402 {test::Quad::SolidColorQuad(1), test::Quad::SolidColorQuad(2)},
403 {test::Quad::SolidColorQuad(3), test::Quad::RenderPassQuad(pass_ids[0])},
404 {test::Quad::SolidColorQuad(4), test::Quad::RenderPassQuad(pass_ids[1])}};
405 test::Pass embedded_passes[] = {
406 test::Pass(embedded_quads[0], arraysize(embedded_quads[0]), pass_ids[0]),
407 test::Pass(embedded_quads[1], arraysize(embedded_quads[1]), pass_ids[1]),
408 test::Pass(embedded_quads[2], arraysize(embedded_quads[2]), pass_ids[2])};
410 SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
412 test::Quad root_quads[][2] = {
413 {test::Quad::SolidColorQuad(5), test::Quad::SolidColorQuad(6)},
414 {test::Quad::SurfaceQuad(embedded_surface_id, 1.f),
415 test::Quad::RenderPassQuad(pass_ids[0])},
416 {test::Quad::SolidColorQuad(7), test::Quad::RenderPassQuad(pass_ids[1])}};
417 test::Pass root_passes[] = {
418 test::Pass(root_quads[0], arraysize(root_quads[0]), pass_ids[0]),
419 test::Pass(root_quads[1], arraysize(root_quads[1]), pass_ids[1]),
420 test::Pass(root_quads[2], arraysize(root_quads[2]), pass_ids[2])};
422 SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
424 scoped_ptr<CompositorFrame> aggregated_frame =
425 aggregator_.Aggregate(root_surface_id_);
427 ASSERT_TRUE(aggregated_frame);
428 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
430 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
432 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
434 ASSERT_EQ(5u, aggregated_pass_list.size());
435 RenderPassId actual_pass_ids[] = {
436 aggregated_pass_list[0]->id, aggregated_pass_list[1]->id,
437 aggregated_pass_list[2]->id, aggregated_pass_list[3]->id,
438 aggregated_pass_list[4]->id};
439 for (size_t i = 0; i < 5; ++i) {
440 for (size_t j = 0; j < i; ++j) {
441 EXPECT_NE(actual_pass_ids[i], actual_pass_ids[j]);
446 SCOPED_TRACE("First pass");
447 // The first pass will just be the first pass from the root surfaces quad
448 // with no render pass quads to remap.
449 TestPassMatchesExpectations(root_passes[0], aggregated_pass_list[0]);
453 SCOPED_TRACE("Second pass");
454 // The next two passes will be from the embedded surface since we have to
455 // draw those passes before they are referenced from the render pass draw
456 // quad embedded into the root surface's second pass.
457 // First, there's the first embedded pass which doesn't reference anything
458 // else.
459 TestPassMatchesExpectations(embedded_passes[0], aggregated_pass_list[1]);
463 SCOPED_TRACE("Third pass");
464 const QuadList& third_pass_quad_list = aggregated_pass_list[2]->quad_list;
465 ASSERT_EQ(2u, third_pass_quad_list.size());
466 TestQuadMatchesExpectations(embedded_quads[1][0],
467 third_pass_quad_list.ElementAt(0));
469 // This render pass pass quad will reference the first pass from the
470 // embedded surface, which is the second pass in the aggregated frame.
471 ASSERT_EQ(DrawQuad::RENDER_PASS,
472 third_pass_quad_list.ElementAt(1)->material);
473 const RenderPassDrawQuad* third_pass_render_pass_draw_quad =
474 RenderPassDrawQuad::MaterialCast(third_pass_quad_list.ElementAt(1));
475 EXPECT_EQ(actual_pass_ids[1],
476 third_pass_render_pass_draw_quad->render_pass_id);
480 SCOPED_TRACE("Fourth pass");
481 // The fourth pass will have aggregated quads from the root surface's second
482 // pass and the embedded surface's first pass.
483 const QuadList& fourth_pass_quad_list = aggregated_pass_list[3]->quad_list;
484 ASSERT_EQ(3u, fourth_pass_quad_list.size());
486 // The first quad will be the yellow quad from the embedded surface's last
487 // pass.
488 TestQuadMatchesExpectations(embedded_quads[2][0],
489 fourth_pass_quad_list.ElementAt(0));
491 // The next quad will be a render pass quad referencing the second pass from
492 // the embedded surface, which is the third pass in the aggregated frame.
493 ASSERT_EQ(DrawQuad::RENDER_PASS,
494 fourth_pass_quad_list.ElementAt(1)->material);
495 const RenderPassDrawQuad* fourth_pass_first_render_pass_draw_quad =
496 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.ElementAt(1));
497 EXPECT_EQ(actual_pass_ids[2],
498 fourth_pass_first_render_pass_draw_quad->render_pass_id);
500 // The last quad will be a render pass quad referencing the first pass from
501 // the root surface, which is the first pass overall.
502 ASSERT_EQ(DrawQuad::RENDER_PASS,
503 fourth_pass_quad_list.ElementAt(2)->material);
504 const RenderPassDrawQuad* fourth_pass_second_render_pass_draw_quad =
505 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.ElementAt(2));
506 EXPECT_EQ(actual_pass_ids[0],
507 fourth_pass_second_render_pass_draw_quad->render_pass_id);
511 SCOPED_TRACE("Fifth pass");
512 const QuadList& fifth_pass_quad_list = aggregated_pass_list[4]->quad_list;
513 ASSERT_EQ(2u, fifth_pass_quad_list.size());
515 TestQuadMatchesExpectations(root_quads[2][0],
516 fifth_pass_quad_list.ElementAt(0));
518 // The last quad in the last pass will reference the second pass from the
519 // root surface, which after aggregating is the fourth pass in the overall
520 // list.
521 ASSERT_EQ(DrawQuad::RENDER_PASS,
522 fifth_pass_quad_list.ElementAt(1)->material);
523 const RenderPassDrawQuad* fifth_pass_render_pass_draw_quad =
524 RenderPassDrawQuad::MaterialCast(fifth_pass_quad_list.ElementAt(1));
525 EXPECT_EQ(actual_pass_ids[3],
526 fifth_pass_render_pass_draw_quad->render_pass_id);
528 factory_.Destroy(embedded_surface_id);
531 // Tests an invalid surface reference in a frame. The surface quad should just
532 // be dropped.
533 TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {
534 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
535 test::Quad::SurfaceQuad(InvalidSurfaceId(), 1.f),
536 test::Quad::SolidColorQuad(SK_ColorBLUE)};
537 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
539 SubmitFrame(passes, arraysize(passes), root_surface_id_);
541 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
542 test::Quad::SolidColorQuad(SK_ColorBLUE)};
543 test::Pass expected_passes[] = {
544 test::Pass(expected_quads, arraysize(expected_quads))};
545 SurfaceId ids[] = {root_surface_id_, InvalidSurfaceId()};
546 AggregateAndVerify(
547 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
550 // Tests a reference to a valid surface with no submitted frame. This quad
551 // should also just be dropped.
552 TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) {
553 SurfaceId surface_with_no_frame_id = allocator_.GenerateId();
554 factory_.Create(surface_with_no_frame_id);
555 test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
556 test::Quad::SurfaceQuad(surface_with_no_frame_id, 1.f),
557 test::Quad::SolidColorQuad(SK_ColorBLUE)};
558 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
560 SubmitFrame(passes, arraysize(passes), root_surface_id_);
562 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
563 test::Quad::SolidColorQuad(SK_ColorBLUE)};
564 test::Pass expected_passes[] = {
565 test::Pass(expected_quads, arraysize(expected_quads))};
566 SurfaceId ids[] = {root_surface_id_, surface_with_no_frame_id};
567 AggregateAndVerify(
568 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
569 factory_.Destroy(surface_with_no_frame_id);
572 // Tests a surface quad referencing itself, generating a trivial cycle.
573 // The quad creating the cycle should be dropped from the final frame.
574 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {
575 test::Quad quads[] = {test::Quad::SurfaceQuad(root_surface_id_, 1.f),
576 test::Quad::SolidColorQuad(SK_ColorYELLOW)};
577 test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
579 SubmitFrame(passes, arraysize(passes), root_surface_id_);
581 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorYELLOW)};
582 test::Pass expected_passes[] = {
583 test::Pass(expected_quads, arraysize(expected_quads))};
584 SurfaceId ids[] = {root_surface_id_};
585 AggregateAndVerify(
586 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
589 // Tests a more complex cycle with one intermediate surface.
590 TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
591 SurfaceId child_surface_id = allocator_.GenerateId();
592 factory_.Create(child_surface_id);
594 test::Quad parent_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
595 test::Quad::SurfaceQuad(child_surface_id, 1.f),
596 test::Quad::SolidColorQuad(SK_ColorCYAN)};
597 test::Pass parent_passes[] = {
598 test::Pass(parent_quads, arraysize(parent_quads))};
600 SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
602 test::Quad child_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
603 test::Quad::SurfaceQuad(root_surface_id_, 1.f),
604 test::Quad::SolidColorQuad(SK_ColorMAGENTA)};
605 test::Pass child_passes[] = {test::Pass(child_quads, arraysize(child_quads))};
607 SubmitFrame(child_passes, arraysize(child_passes), child_surface_id);
609 // The child surface's reference to the root_surface_ will be dropped, so
610 // we'll end up with:
611 // SK_ColorBLUE from the parent
612 // SK_ColorGREEN from the child
613 // SK_ColorMAGENTA from the child
614 // SK_ColorCYAN from the parent
615 test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
616 test::Quad::SolidColorQuad(SK_ColorGREEN),
617 test::Quad::SolidColorQuad(SK_ColorMAGENTA),
618 test::Quad::SolidColorQuad(SK_ColorCYAN)};
619 test::Pass expected_passes[] = {
620 test::Pass(expected_quads, arraysize(expected_quads))};
621 SurfaceId ids[] = {root_surface_id_, child_surface_id};
622 AggregateAndVerify(
623 expected_passes, arraysize(expected_passes), ids, arraysize(ids));
624 factory_.Destroy(child_surface_id);
627 // Tests that we map render pass IDs from different surfaces into a unified
628 // namespace and update RenderPassDrawQuad's id references to match.
629 TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
630 SurfaceId child_surface_id = allocator_.GenerateId();
631 factory_.Create(child_surface_id);
633 RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
634 test::Quad child_quad[][1] = {{test::Quad::SolidColorQuad(SK_ColorGREEN)},
635 {test::Quad::RenderPassQuad(child_pass_id[0])}};
636 test::Pass surface_passes[] = {
637 test::Pass(child_quad[0], arraysize(child_quad[0]), child_pass_id[0]),
638 test::Pass(child_quad[1], arraysize(child_quad[1]), child_pass_id[1])};
640 SubmitFrame(surface_passes, arraysize(surface_passes), child_surface_id);
642 // Pass IDs from the parent surface may collide with ones from the child.
643 RenderPassId parent_pass_id[] = {RenderPassId(2, 1), RenderPassId(1, 2)};
644 test::Quad parent_quad[][1] = {
645 {test::Quad::SurfaceQuad(child_surface_id, 1.f)},
646 {test::Quad::RenderPassQuad(parent_pass_id[0])}};
647 test::Pass parent_passes[] = {
648 test::Pass(parent_quad[0], arraysize(parent_quad[0]), parent_pass_id[0]),
649 test::Pass(parent_quad[1], arraysize(parent_quad[1]), parent_pass_id[1])};
651 SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
652 scoped_ptr<CompositorFrame> aggregated_frame =
653 aggregator_.Aggregate(root_surface_id_);
655 ASSERT_TRUE(aggregated_frame);
656 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
658 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
660 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
662 ASSERT_EQ(3u, aggregated_pass_list.size());
663 RenderPassId actual_pass_ids[] = {aggregated_pass_list[0]->id,
664 aggregated_pass_list[1]->id,
665 aggregated_pass_list[2]->id};
666 // Make sure the aggregated frame's pass IDs are all unique.
667 for (size_t i = 0; i < 3; ++i) {
668 for (size_t j = 0; j < i; ++j) {
669 EXPECT_NE(actual_pass_ids[j], actual_pass_ids[i]) << "pass ids " << i
670 << " and " << j;
674 // Make sure the render pass quads reference the remapped pass IDs.
675 DrawQuad* render_pass_quads[] = {aggregated_pass_list[1]->quad_list.front(),
676 aggregated_pass_list[2]->quad_list.front()};
677 ASSERT_EQ(render_pass_quads[0]->material, DrawQuad::RENDER_PASS);
678 EXPECT_EQ(
679 actual_pass_ids[0],
680 RenderPassDrawQuad::MaterialCast(render_pass_quads[0])->render_pass_id);
682 ASSERT_EQ(render_pass_quads[1]->material, DrawQuad::RENDER_PASS);
683 EXPECT_EQ(
684 actual_pass_ids[1],
685 RenderPassDrawQuad::MaterialCast(render_pass_quads[1])->render_pass_id);
686 factory_.Destroy(child_surface_id);
689 void AddSolidColorQuadWithBlendMode(const gfx::Size& size,
690 RenderPass* pass,
691 const SkXfermode::Mode blend_mode) {
692 const gfx::Transform content_to_target_transform;
693 const gfx::Size content_bounds(size);
694 const gfx::Rect visible_content_rect(size);
695 const gfx::Rect clip_rect(size);
697 bool is_clipped = false;
698 float opacity = 1.f;
700 bool force_anti_aliasing_off = false;
701 SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
702 sqs->SetAll(content_to_target_transform,
703 content_bounds,
704 visible_content_rect,
705 clip_rect,
706 is_clipped,
707 opacity,
708 blend_mode,
711 SolidColorDrawQuad* color_quad =
712 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
713 color_quad->SetNew(pass->shared_quad_state_list.back(),
714 visible_content_rect,
715 visible_content_rect,
716 SK_ColorGREEN,
717 force_anti_aliasing_off);
720 // This tests that we update shared quad state pointers correctly within
721 // aggregated passes. The shared quad state list on the aggregated pass will
722 // include the shared quad states from each pass in one list so the quads will
723 // end up pointed to shared quad state objects at different offsets. This test
724 // uses the blend_mode value stored on the shared quad state to track the shared
725 // quad state, but anything saved on the shared quad state would work.
727 // This test has 4 surfaces in the following structure:
728 // root_surface -> quad with kClear_Mode,
729 // [child_one_surface],
730 // quad with kDstOver_Mode,
731 // [child_two_surface],
732 // quad with kDstIn_Mode
733 // child_one_surface -> quad with kSrc_Mode,
734 // [grandchild_surface],
735 // quad with kSrcOver_Mode
736 // child_two_surface -> quad with kSrcIn_Mode
737 // grandchild_surface -> quad with kDst_Mode
739 // Resulting in the following aggregated pass:
740 // quad_root_0 - blend_mode kClear_Mode
741 // quad_child_one_0 - blend_mode kSrc_Mode
742 // quad_grandchild_0 - blend_mode kDst_Mode
743 // quad_child_one_1 - blend_mode kSrcOver_Mode
744 // quad_root_1 - blend_mode kDstOver_Mode
745 // quad_child_two_0 - blend_mode kSrcIn_Mode
746 // quad_root_2 - blend_mode kDstIn_Mode
747 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
748 const SkXfermode::Mode blend_modes[] = {SkXfermode::kClear_Mode, // 0
749 SkXfermode::kSrc_Mode, // 1
750 SkXfermode::kDst_Mode, // 2
751 SkXfermode::kSrcOver_Mode, // 3
752 SkXfermode::kDstOver_Mode, // 4
753 SkXfermode::kSrcIn_Mode, // 5
754 SkXfermode::kDstIn_Mode, // 6
757 RenderPassId pass_id(1, 1);
758 SurfaceId grandchild_surface_id = allocator_.GenerateId();
759 factory_.Create(grandchild_surface_id);
760 scoped_ptr<RenderPass> grandchild_pass = RenderPass::Create();
761 gfx::Rect output_rect(SurfaceSize());
762 gfx::Rect damage_rect(SurfaceSize());
763 gfx::Transform transform_to_root_target;
764 grandchild_pass->SetNew(
765 pass_id, output_rect, damage_rect, transform_to_root_target);
766 AddSolidColorQuadWithBlendMode(
767 SurfaceSize(), grandchild_pass.get(), blend_modes[2]);
768 QueuePassAsFrame(grandchild_pass.Pass(), grandchild_surface_id);
770 SurfaceId child_one_surface_id = allocator_.GenerateId();
771 factory_.Create(child_one_surface_id);
773 scoped_ptr<RenderPass> child_one_pass = RenderPass::Create();
774 child_one_pass->SetNew(
775 pass_id, output_rect, damage_rect, transform_to_root_target);
776 AddSolidColorQuadWithBlendMode(
777 SurfaceSize(), child_one_pass.get(), blend_modes[1]);
778 SurfaceDrawQuad* grandchild_surface_quad =
779 child_one_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
780 grandchild_surface_quad->SetNew(child_one_pass->shared_quad_state_list.back(),
781 gfx::Rect(SurfaceSize()),
782 gfx::Rect(SurfaceSize()),
783 grandchild_surface_id);
784 AddSolidColorQuadWithBlendMode(
785 SurfaceSize(), child_one_pass.get(), blend_modes[3]);
786 QueuePassAsFrame(child_one_pass.Pass(), child_one_surface_id);
788 SurfaceId child_two_surface_id = allocator_.GenerateId();
789 factory_.Create(child_two_surface_id);
791 scoped_ptr<RenderPass> child_two_pass = RenderPass::Create();
792 child_two_pass->SetNew(
793 pass_id, output_rect, damage_rect, transform_to_root_target);
794 AddSolidColorQuadWithBlendMode(
795 SurfaceSize(), child_two_pass.get(), blend_modes[5]);
796 QueuePassAsFrame(child_two_pass.Pass(), child_two_surface_id);
798 scoped_ptr<RenderPass> root_pass = RenderPass::Create();
799 root_pass->SetNew(
800 pass_id, output_rect, damage_rect, transform_to_root_target);
802 AddSolidColorQuadWithBlendMode(
803 SurfaceSize(), root_pass.get(), blend_modes[0]);
804 SurfaceDrawQuad* child_one_surface_quad =
805 root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
806 child_one_surface_quad->SetNew(root_pass->shared_quad_state_list.back(),
807 gfx::Rect(SurfaceSize()),
808 gfx::Rect(SurfaceSize()),
809 child_one_surface_id);
810 AddSolidColorQuadWithBlendMode(
811 SurfaceSize(), root_pass.get(), blend_modes[4]);
812 SurfaceDrawQuad* child_two_surface_quad =
813 root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
814 child_two_surface_quad->SetNew(root_pass->shared_quad_state_list.back(),
815 gfx::Rect(SurfaceSize()),
816 gfx::Rect(SurfaceSize()),
817 child_two_surface_id);
818 AddSolidColorQuadWithBlendMode(
819 SurfaceSize(), root_pass.get(), blend_modes[6]);
821 QueuePassAsFrame(root_pass.Pass(), root_surface_id_);
823 scoped_ptr<CompositorFrame> aggregated_frame =
824 aggregator_.Aggregate(root_surface_id_);
826 ASSERT_TRUE(aggregated_frame);
827 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
829 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
831 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
833 ASSERT_EQ(1u, aggregated_pass_list.size());
835 const QuadList& aggregated_quad_list = aggregated_pass_list[0]->quad_list;
837 ASSERT_EQ(7u, aggregated_quad_list.size());
839 for (auto iter = aggregated_quad_list.cbegin();
840 iter != aggregated_quad_list.cend();
841 ++iter) {
842 EXPECT_EQ(blend_modes[iter.index()], iter->shared_quad_state->blend_mode)
843 << iter.index();
845 factory_.Destroy(child_one_surface_id);
846 factory_.Destroy(child_two_surface_id);
847 factory_.Destroy(grandchild_surface_id);
850 // This tests that when aggregating a frame with multiple render passes that we
851 // map the transforms for the root pass but do not modify the transform on child
852 // passes.
854 // The root surface has one pass with a surface quad transformed by +10 in the y
855 // direction.
857 // The middle surface has one pass with a surface quad scaled by 2 in the x
858 // and 3 in the y directions.
860 // The child surface has two passes. The first pass has a quad with a transform
861 // of +5 in the x direction. The second pass has a reference to the first pass'
862 // pass id and a transform of +8 in the x direction.
864 // After aggregation, the child surface's root pass quad should have all
865 // transforms concatenated for a total transform of +23 x, +10 y. The
866 // contributing render pass' transform in the aggregate frame should not be
867 // affected.
868 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
869 // Innermost child surface.
870 SurfaceId child_surface_id = allocator_.GenerateId();
872 factory_.Create(child_surface_id);
873 RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
874 test::Quad child_quads[][1] = {
875 {test::Quad::SolidColorQuad(SK_ColorGREEN)},
876 {test::Quad::RenderPassQuad(child_pass_id[0])},
878 test::Pass child_passes[] = {
879 test::Pass(child_quads[0], arraysize(child_quads[0]), child_pass_id[0]),
880 test::Pass(child_quads[1], arraysize(child_quads[1]),
881 child_pass_id[1])};
883 RenderPassList child_pass_list;
884 AddPasses(&child_pass_list, gfx::Rect(SurfaceSize()), child_passes,
885 arraysize(child_passes));
887 RenderPass* child_nonroot_pass = child_pass_list.at(0u);
888 child_nonroot_pass->transform_to_root_target.Translate(8, 0);
889 SharedQuadState* child_nonroot_pass_sqs =
890 child_nonroot_pass->shared_quad_state_list.front();
891 child_nonroot_pass_sqs->content_to_target_transform.Translate(5, 0);
893 RenderPass* child_root_pass = child_pass_list.at(1u);
894 SharedQuadState* child_root_pass_sqs =
895 child_root_pass->shared_quad_state_list.front();
896 child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
897 child_root_pass_sqs->is_clipped = true;
898 child_root_pass_sqs->clip_rect = gfx::Rect(0, 0, 5, 5);
900 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
901 child_pass_list.swap(child_frame_data->render_pass_list);
903 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
904 child_frame->delegated_frame_data = child_frame_data.Pass();
906 factory_.SubmitFrame(child_surface_id, child_frame.Pass(),
907 SurfaceFactory::DrawCallback());
910 // Middle child surface.
911 SurfaceId middle_surface_id = allocator_.GenerateId();
913 factory_.Create(middle_surface_id);
914 test::Quad middle_quads[] = {
915 test::Quad::SurfaceQuad(child_surface_id, 1.f)};
916 test::Pass middle_passes[] = {
917 test::Pass(middle_quads, arraysize(middle_quads)),
920 RenderPassList middle_pass_list;
921 AddPasses(&middle_pass_list, gfx::Rect(SurfaceSize()), middle_passes,
922 arraysize(middle_passes));
924 RenderPass* middle_root_pass = middle_pass_list.at(0u);
925 middle_root_pass->quad_list.ElementAt(0)->visible_rect =
926 gfx::Rect(0, 1, 100, 7);
927 SharedQuadState* middle_root_pass_sqs =
928 middle_root_pass->shared_quad_state_list.front();
929 middle_root_pass_sqs->content_to_target_transform.Scale(2, 3);
931 scoped_ptr<DelegatedFrameData> middle_frame_data(new DelegatedFrameData);
932 middle_pass_list.swap(middle_frame_data->render_pass_list);
934 scoped_ptr<CompositorFrame> middle_frame(new CompositorFrame);
935 middle_frame->delegated_frame_data = middle_frame_data.Pass();
937 factory_.SubmitFrame(middle_surface_id, middle_frame.Pass(),
938 SurfaceFactory::DrawCallback());
941 // Root surface.
942 test::Quad root_quads[] = {test::Quad::SolidColorQuad(1),
943 test::Quad::SurfaceQuad(middle_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);
958 root_pass_list.at(0)->quad_list.ElementAt(1)->visible_rect =
959 gfx::Rect(0, 0, 8, 100);
961 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
962 root_pass_list.swap(root_frame_data->render_pass_list);
964 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
965 root_frame->delegated_frame_data = root_frame_data.Pass();
967 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
968 SurfaceFactory::DrawCallback());
970 scoped_ptr<CompositorFrame> aggregated_frame =
971 aggregator_.Aggregate(root_surface_id_);
973 ASSERT_TRUE(aggregated_frame);
974 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
976 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
978 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
980 ASSERT_EQ(2u, aggregated_pass_list.size());
982 ASSERT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
984 // The first pass should have one shared quad state for the one solid color
985 // quad.
986 EXPECT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
987 // The second (root) pass should have just two shared quad states. We'll
988 // verify the properties through the quads.
989 EXPECT_EQ(2u, aggregated_pass_list[1]->shared_quad_state_list.size());
991 SharedQuadState* aggregated_first_pass_sqs =
992 aggregated_pass_list[0]->shared_quad_state_list.front();
994 // The first pass's transform should be unaffected by the embedding and still
995 // be a translation by +5 in the x direction.
996 gfx::Transform expected_aggregated_first_pass_sqs_transform;
997 expected_aggregated_first_pass_sqs_transform.Translate(5, 0);
998 EXPECT_EQ(expected_aggregated_first_pass_sqs_transform.ToString(),
999 aggregated_first_pass_sqs->content_to_target_transform.ToString());
1001 // The first pass's transform to the root target should include the aggregated
1002 // transform.
1003 gfx::Transform expected_first_pass_transform_to_root_target;
1004 expected_first_pass_transform_to_root_target.Translate(0, 10);
1005 expected_first_pass_transform_to_root_target.Scale(2, 3);
1006 expected_first_pass_transform_to_root_target.Translate(8, 0);
1007 EXPECT_EQ(expected_first_pass_transform_to_root_target.ToString(),
1008 aggregated_pass_list[0]->transform_to_root_target.ToString());
1010 ASSERT_EQ(2u, aggregated_pass_list[1]->quad_list.size());
1012 gfx::Transform expected_root_pass_quad_transforms[2];
1013 // The first quad in the root pass is the solid color quad from the original
1014 // root surface. Its transform should be unaffected by the aggregation and
1015 // still be +7 in the y direction.
1016 expected_root_pass_quad_transforms[0].Translate(0, 7);
1017 // The second quad in the root pass is aggregated from the child surface so
1018 // its transform should be the combination of its original translation
1019 // (0, 10), the middle surface draw quad's scale of (2, 3), and the
1020 // child surface draw quad's translation (8, 0).
1021 expected_root_pass_quad_transforms[1].Translate(0, 10);
1022 expected_root_pass_quad_transforms[1].Scale(2, 3);
1023 expected_root_pass_quad_transforms[1].Translate(8, 0);
1025 for (auto iter = aggregated_pass_list[1]->quad_list.cbegin();
1026 iter != aggregated_pass_list[1]->quad_list.cend();
1027 ++iter) {
1028 EXPECT_EQ(expected_root_pass_quad_transforms[iter.index()].ToString(),
1029 iter->quadTransform().ToString())
1030 << iter.index();
1033 EXPECT_TRUE(
1034 aggregated_pass_list[1]->shared_quad_state_list.ElementAt(1)->is_clipped);
1036 // The second quad in the root pass is aggregated from the child, so its
1037 // clip rect must be transformed by the child's translation/scale and
1038 // clipped be the visible_rects for both children.
1039 EXPECT_EQ(gfx::Rect(0, 13, 8, 12).ToString(),
1040 aggregated_pass_list[1]
1041 ->shared_quad_state_list.ElementAt(1)
1042 ->clip_rect.ToString());
1044 factory_.Destroy(middle_surface_id);
1045 factory_.Destroy(child_surface_id);
1048 // Tests that damage rects are aggregated correctly when surfaces change.
1049 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
1050 SurfaceId child_surface_id = allocator_.GenerateId();
1051 factory_.Create(child_surface_id);
1052 RenderPassId child_pass_id = RenderPassId(1, 1);
1053 test::Quad child_quads[] = {test::Quad::RenderPassQuad(child_pass_id)};
1054 test::Pass child_passes[] = {
1055 test::Pass(child_quads, arraysize(child_quads), child_pass_id)};
1057 RenderPassList child_pass_list;
1058 AddPasses(&child_pass_list,
1059 gfx::Rect(SurfaceSize()),
1060 child_passes,
1061 arraysize(child_passes));
1063 RenderPass* child_root_pass = child_pass_list.at(0u);
1064 SharedQuadState* child_root_pass_sqs =
1065 child_root_pass->shared_quad_state_list.front();
1066 child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
1068 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
1069 child_pass_list.swap(child_frame_data->render_pass_list);
1071 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
1072 child_frame->delegated_frame_data = child_frame_data.Pass();
1074 factory_.SubmitFrame(child_surface_id, child_frame.Pass(),
1075 SurfaceFactory::DrawCallback());
1077 test::Quad root_quads[] = {test::Quad::SurfaceQuad(child_surface_id, 1.f)};
1078 test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
1080 RenderPassList root_pass_list;
1081 AddPasses(&root_pass_list,
1082 gfx::Rect(SurfaceSize()),
1083 root_passes,
1084 arraysize(root_passes));
1086 root_pass_list.at(0)
1087 ->shared_quad_state_list.front()
1088 ->content_to_target_transform.Translate(0, 10);
1089 root_pass_list.at(0)->damage_rect = gfx::Rect(5, 5, 10, 10);
1091 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1092 root_pass_list.swap(root_frame_data->render_pass_list);
1094 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1095 root_frame->delegated_frame_data = root_frame_data.Pass();
1097 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
1098 SurfaceFactory::DrawCallback());
1100 scoped_ptr<CompositorFrame> aggregated_frame =
1101 aggregator_.Aggregate(root_surface_id_);
1103 ASSERT_TRUE(aggregated_frame);
1104 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1106 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
1108 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1110 ASSERT_EQ(1u, aggregated_pass_list.size());
1112 // Damage rect for first aggregation should contain entire root surface.
1113 EXPECT_TRUE(
1114 aggregated_pass_list[0]->damage_rect.Contains(gfx::Rect(SurfaceSize())));
1117 AddPasses(&child_pass_list,
1118 gfx::Rect(SurfaceSize()),
1119 child_passes,
1120 arraysize(child_passes));
1122 RenderPass* child_root_pass = child_pass_list.at(0u);
1123 SharedQuadState* child_root_pass_sqs =
1124 child_root_pass->shared_quad_state_list.front();
1125 child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
1126 child_root_pass->damage_rect = gfx::Rect(10, 10, 10, 10);
1128 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
1129 child_pass_list.swap(child_frame_data->render_pass_list);
1131 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
1132 child_frame->delegated_frame_data = child_frame_data.Pass();
1134 factory_.SubmitFrame(child_surface_id, child_frame.Pass(),
1135 SurfaceFactory::DrawCallback());
1137 scoped_ptr<CompositorFrame> aggregated_frame =
1138 aggregator_.Aggregate(root_surface_id_);
1140 ASSERT_TRUE(aggregated_frame);
1141 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1143 DelegatedFrameData* frame_data =
1144 aggregated_frame->delegated_frame_data.get();
1146 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1148 ASSERT_EQ(1u, aggregated_pass_list.size());
1150 // Outer surface didn't change, so transformed inner damage rect should be
1151 // used.
1152 EXPECT_EQ(gfx::Rect(10, 20, 10, 10).ToString(),
1153 aggregated_pass_list[0]->damage_rect.ToString());
1157 RenderPassList root_pass_list;
1158 AddPasses(&root_pass_list,
1159 gfx::Rect(SurfaceSize()),
1160 root_passes,
1161 arraysize(root_passes));
1163 root_pass_list.at(0)
1164 ->shared_quad_state_list.front()
1165 ->content_to_target_transform.Translate(0, 10);
1166 root_pass_list.at(0)->damage_rect = gfx::Rect(0, 0, 1, 1);
1168 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1169 root_pass_list.swap(root_frame_data->render_pass_list);
1171 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1172 root_frame->delegated_frame_data = root_frame_data.Pass();
1174 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
1175 SurfaceFactory::DrawCallback());
1179 RenderPassList root_pass_list;
1180 AddPasses(&root_pass_list,
1181 gfx::Rect(SurfaceSize()),
1182 root_passes,
1183 arraysize(root_passes));
1185 root_pass_list.at(0)
1186 ->shared_quad_state_list.front()
1187 ->content_to_target_transform.Translate(0, 10);
1188 root_pass_list.at(0)->damage_rect = gfx::Rect(1, 1, 1, 1);
1190 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1191 root_pass_list.swap(root_frame_data->render_pass_list);
1193 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1194 root_frame->delegated_frame_data = root_frame_data.Pass();
1196 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
1197 SurfaceFactory::DrawCallback());
1199 scoped_ptr<CompositorFrame> aggregated_frame =
1200 aggregator_.Aggregate(root_surface_id_);
1202 ASSERT_TRUE(aggregated_frame);
1203 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1205 DelegatedFrameData* frame_data =
1206 aggregated_frame->delegated_frame_data.get();
1208 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1210 ASSERT_EQ(1u, aggregated_pass_list.size());
1212 // The root surface was enqueued without being aggregated once, so it should
1213 // be treated as completely damaged.
1214 EXPECT_TRUE(aggregated_pass_list[0]->damage_rect.Contains(
1215 gfx::Rect(SurfaceSize())));
1218 factory_.Destroy(child_surface_id);
1221 class SurfaceAggregatorWithResourcesTest : public testing::Test {
1222 public:
1223 void SetUp() override {
1224 output_surface_ = FakeOutputSurface::CreateSoftware(
1225 make_scoped_ptr(new SoftwareOutputDevice));
1226 output_surface_->BindToClient(&output_surface_client_);
1227 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
1229 resource_provider_ = ResourceProvider::Create(output_surface_.get(),
1230 shared_bitmap_manager_.get(),
1231 NULL,
1232 NULL,
1234 false,
1237 aggregator_.reset(
1238 new SurfaceAggregator(&manager_, resource_provider_.get()));
1241 protected:
1242 SurfaceManager manager_;
1243 FakeOutputSurfaceClient output_surface_client_;
1244 scoped_ptr<OutputSurface> output_surface_;
1245 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
1246 scoped_ptr<ResourceProvider> resource_provider_;
1247 scoped_ptr<SurfaceAggregator> aggregator_;
1250 class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient {
1251 public:
1252 ResourceTrackingSurfaceFactoryClient() {}
1253 ~ResourceTrackingSurfaceFactoryClient() override {}
1255 void ReturnResources(const ReturnedResourceArray& resources) override {
1256 returned_resources_ = resources;
1259 ReturnedResourceArray returned_resources() const {
1260 return returned_resources_;
1263 private:
1264 ReturnedResourceArray returned_resources_;
1266 DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient);
1269 void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids,
1270 size_t num_resource_ids,
1271 SurfaceFactory* factory,
1272 SurfaceId surface_id) {
1273 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
1274 scoped_ptr<RenderPass> pass = RenderPass::Create();
1275 pass->id = RenderPassId(1, 1);
1276 SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
1277 for (size_t i = 0u; i < num_resource_ids; ++i) {
1278 TransferableResource resource;
1279 resource.id = resource_ids[i];
1280 resource.is_software = true;
1281 frame_data->resource_list.push_back(resource);
1282 TextureDrawQuad* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
1283 const gfx::Rect rect;
1284 const gfx::Rect opaque_rect;
1285 const gfx::Rect visible_rect;
1286 bool needs_blending = false;
1287 bool premultiplied_alpha = false;
1288 const gfx::PointF uv_top_left;
1289 const gfx::PointF uv_bottom_right;
1290 SkColor background_color = SK_ColorGREEN;
1291 const float vertex_opacity[4] = {0.f, 0.f, 1.f, 1.f};
1292 bool flipped = false;
1293 bool nearest_neighbor = false;
1294 quad->SetAll(sqs,
1295 rect,
1296 opaque_rect,
1297 visible_rect,
1298 needs_blending,
1299 resource_ids[i],
1300 premultiplied_alpha,
1301 uv_top_left,
1302 uv_bottom_right,
1303 background_color,
1304 vertex_opacity,
1305 flipped,
1306 nearest_neighbor);
1308 quad->shared_quad_state = sqs;
1310 frame_data->render_pass_list.push_back(pass.Pass());
1311 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
1312 frame->delegated_frame_data = frame_data.Pass();
1313 factory->SubmitFrame(surface_id, frame.Pass(),
1314 SurfaceFactory::DrawCallback());
1317 TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
1318 ResourceTrackingSurfaceFactoryClient client;
1319 SurfaceFactory factory(&manager_, &client);
1320 SurfaceId surface_id(7u);
1321 factory.Create(surface_id);
1323 ResourceProvider::ResourceId ids[] = {11, 12, 13};
1324 SubmitFrameWithResources(ids, arraysize(ids), &factory, surface_id);
1326 scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id);
1328 // Nothing should be available to be returned yet.
1329 EXPECT_TRUE(client.returned_resources().empty());
1331 SubmitFrameWithResources(NULL, 0u, &factory, surface_id);
1333 frame = aggregator_->Aggregate(surface_id);
1335 ASSERT_EQ(3u, client.returned_resources().size());
1336 ResourceProvider::ResourceId returned_ids[3];
1337 for (size_t i = 0; i < 3; ++i) {
1338 returned_ids[i] = client.returned_resources()[i].id;
1340 EXPECT_THAT(returned_ids,
1341 testing::WhenSorted(testing::ElementsAreArray(ids)));
1342 factory.Destroy(surface_id);
1345 TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) {
1346 ResourceTrackingSurfaceFactoryClient client;
1347 SurfaceFactory factory(&manager_, &client);
1348 SurfaceId surface_id(7u);
1349 factory.Create(surface_id);
1351 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
1352 scoped_ptr<RenderPass> pass = RenderPass::Create();
1353 pass->id = RenderPassId(1, 1);
1354 TransferableResource resource;
1355 resource.id = 11;
1356 // ResourceProvider is software but resource is not, so it should be
1357 // ignored.
1358 resource.is_software = false;
1359 frame_data->resource_list.push_back(resource);
1360 frame_data->render_pass_list.push_back(pass.Pass());
1361 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
1362 frame->delegated_frame_data = frame_data.Pass();
1363 factory.SubmitFrame(surface_id, frame.Pass(), SurfaceFactory::DrawCallback());
1365 scoped_ptr<CompositorFrame> returned_frame =
1366 aggregator_->Aggregate(surface_id);
1368 // Nothing should be available to be returned yet.
1369 EXPECT_TRUE(client.returned_resources().empty());
1371 SubmitFrameWithResources(NULL, 0u, &factory, surface_id);
1372 ASSERT_EQ(1u, client.returned_resources().size());
1373 EXPECT_EQ(11u, client.returned_resources()[0].id);
1375 factory.Destroy(surface_id);
1378 TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) {
1379 ResourceTrackingSurfaceFactoryClient client;
1380 SurfaceFactory factory(&manager_, &client);
1381 SurfaceId surface_id(7u);
1382 factory.Create(surface_id);
1383 SurfaceId surface_id2(8u);
1384 factory.Create(surface_id2);
1386 ResourceProvider::ResourceId ids[] = {11, 12, 13};
1387 SubmitFrameWithResources(ids, arraysize(ids), &factory, surface_id);
1388 ResourceProvider::ResourceId ids2[] = {14, 15, 16};
1389 SubmitFrameWithResources(ids2, arraysize(ids2), &factory, surface_id2);
1391 scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id);
1393 SubmitFrameWithResources(NULL, 0, &factory, surface_id);
1395 // Nothing should be available to be returned yet.
1396 EXPECT_TRUE(client.returned_resources().empty());
1398 frame = aggregator_->Aggregate(surface_id2);
1400 // surface_id wasn't referenced, so its resources should be returned.
1401 ASSERT_EQ(3u, client.returned_resources().size());
1402 ResourceProvider::ResourceId returned_ids[3];
1403 for (size_t i = 0; i < 3; ++i) {
1404 returned_ids[i] = client.returned_resources()[i].id;
1406 EXPECT_THAT(returned_ids,
1407 testing::WhenSorted(testing::ElementsAreArray(ids)));
1408 EXPECT_EQ(3u, resource_provider_->num_resources());
1409 factory.Destroy(surface_id);
1410 factory.Destroy(surface_id2);
1413 } // namespace
1414 } // namespace cc