Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / cc / surfaces / surface_aggregator_unittest.cc
blob72aa3f120ed6ae1a2272ad48e47e323cc8460b7b
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 secondary_quads[] = {
943 test::Quad::SolidColorQuad(1),
944 test::Quad::SurfaceQuad(middle_surface_id, 1.f)};
945 test::Quad root_quads[] = {test::Quad::SolidColorQuad(1)};
946 test::Pass root_passes[] = {
947 test::Pass(secondary_quads, arraysize(secondary_quads)),
948 test::Pass(root_quads, arraysize(root_quads))};
950 RenderPassList root_pass_list;
951 AddPasses(&root_pass_list,
952 gfx::Rect(SurfaceSize()),
953 root_passes,
954 arraysize(root_passes));
956 root_pass_list.at(0)
957 ->shared_quad_state_list.front()
958 ->content_to_target_transform.Translate(0, 7);
959 root_pass_list.at(0)
960 ->shared_quad_state_list.ElementAt(1)
961 ->content_to_target_transform.Translate(0, 10);
962 root_pass_list.at(0)->quad_list.ElementAt(1)->visible_rect =
963 gfx::Rect(0, 0, 8, 100);
965 root_pass_list[0]->transform_to_root_target.Translate(10, 5);
967 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
968 root_pass_list.swap(root_frame_data->render_pass_list);
970 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
971 root_frame->delegated_frame_data = root_frame_data.Pass();
973 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
974 SurfaceFactory::DrawCallback());
976 scoped_ptr<CompositorFrame> aggregated_frame =
977 aggregator_.Aggregate(root_surface_id_);
979 ASSERT_TRUE(aggregated_frame);
980 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
982 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
984 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
986 ASSERT_EQ(3u, aggregated_pass_list.size());
988 ASSERT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
990 // The first pass should have one shared quad state for the one solid color
991 // quad.
992 EXPECT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
993 // The second pass should have just two shared quad states. We'll
994 // verify the properties through the quads.
995 EXPECT_EQ(2u, aggregated_pass_list[1]->shared_quad_state_list.size());
997 EXPECT_EQ(1u, aggregated_pass_list[2]->shared_quad_state_list.size());
999 SharedQuadState* aggregated_first_pass_sqs =
1000 aggregated_pass_list[0]->shared_quad_state_list.front();
1002 // The first pass's transform should be unaffected by the embedding and still
1003 // be a translation by +5 in the x direction.
1004 gfx::Transform expected_aggregated_first_pass_sqs_transform;
1005 expected_aggregated_first_pass_sqs_transform.Translate(5, 0);
1006 EXPECT_EQ(expected_aggregated_first_pass_sqs_transform.ToString(),
1007 aggregated_first_pass_sqs->content_to_target_transform.ToString());
1009 // The first pass's transform to the root target should include the aggregated
1010 // transform, including the transform from the child pass to the root.
1011 gfx::Transform expected_first_pass_transform_to_root_target;
1012 expected_first_pass_transform_to_root_target.Translate(10, 5);
1013 expected_first_pass_transform_to_root_target.Translate(0, 10);
1014 expected_first_pass_transform_to_root_target.Scale(2, 3);
1015 expected_first_pass_transform_to_root_target.Translate(8, 0);
1016 EXPECT_EQ(expected_first_pass_transform_to_root_target.ToString(),
1017 aggregated_pass_list[0]->transform_to_root_target.ToString());
1019 ASSERT_EQ(2u, aggregated_pass_list[1]->quad_list.size());
1021 gfx::Transform expected_root_pass_quad_transforms[2];
1022 // The first quad in the root pass is the solid color quad from the original
1023 // root surface. Its transform should be unaffected by the aggregation and
1024 // still be +7 in the y direction.
1025 expected_root_pass_quad_transforms[0].Translate(0, 7);
1026 // The second quad in the root pass is aggregated from the child surface so
1027 // its transform should be the combination of its original translation
1028 // (0, 10), the middle surface draw quad's scale of (2, 3), and the
1029 // child surface draw quad's translation (8, 0).
1030 expected_root_pass_quad_transforms[1].Translate(0, 10);
1031 expected_root_pass_quad_transforms[1].Scale(2, 3);
1032 expected_root_pass_quad_transforms[1].Translate(8, 0);
1034 for (auto iter = aggregated_pass_list[1]->quad_list.cbegin();
1035 iter != aggregated_pass_list[1]->quad_list.cend();
1036 ++iter) {
1037 EXPECT_EQ(expected_root_pass_quad_transforms[iter.index()].ToString(),
1038 iter->quadTransform().ToString())
1039 << iter.index();
1042 EXPECT_TRUE(
1043 aggregated_pass_list[1]->shared_quad_state_list.ElementAt(1)->is_clipped);
1045 // The second quad in the root pass is aggregated from the child, so its
1046 // clip rect must be transformed by the child's translation/scale and
1047 // clipped be the visible_rects for both children.
1048 EXPECT_EQ(gfx::Rect(0, 13, 8, 12).ToString(),
1049 aggregated_pass_list[1]
1050 ->shared_quad_state_list.ElementAt(1)
1051 ->clip_rect.ToString());
1053 factory_.Destroy(middle_surface_id);
1054 factory_.Destroy(child_surface_id);
1057 // Tests that damage rects are aggregated correctly when surfaces change.
1058 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
1059 SurfaceId child_surface_id = allocator_.GenerateId();
1060 factory_.Create(child_surface_id);
1061 RenderPassId child_pass_id = RenderPassId(1, 1);
1062 test::Quad child_quads[] = {test::Quad::RenderPassQuad(child_pass_id)};
1063 test::Pass child_passes[] = {
1064 test::Pass(child_quads, arraysize(child_quads), child_pass_id)};
1066 RenderPassList child_pass_list;
1067 AddPasses(&child_pass_list,
1068 gfx::Rect(SurfaceSize()),
1069 child_passes,
1070 arraysize(child_passes));
1072 RenderPass* child_root_pass = child_pass_list.at(0u);
1073 SharedQuadState* child_root_pass_sqs =
1074 child_root_pass->shared_quad_state_list.front();
1075 child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
1077 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
1078 child_pass_list.swap(child_frame_data->render_pass_list);
1080 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
1081 child_frame->delegated_frame_data = child_frame_data.Pass();
1083 factory_.SubmitFrame(child_surface_id, child_frame.Pass(),
1084 SurfaceFactory::DrawCallback());
1086 RenderPassId pass_id(5, 10);
1087 test::Quad first_quads[] = {test::Quad::SurfaceQuad(child_surface_id, 1.f)};
1088 test::Quad root_quads[] = {test::Quad::RenderPassQuad(pass_id)};
1090 test::Pass root_passes[] = {
1091 test::Pass(first_quads, arraysize(first_quads), pass_id),
1092 test::Pass(root_quads, arraysize(root_quads))};
1094 RenderPassList root_pass_list;
1095 AddPasses(&root_pass_list,
1096 gfx::Rect(SurfaceSize()),
1097 root_passes,
1098 arraysize(root_passes));
1100 root_pass_list.at(0)
1101 ->shared_quad_state_list.front()
1102 ->content_to_target_transform.Translate(0, 10);
1103 root_pass_list.at(0)->damage_rect = gfx::Rect(5, 5, 10, 10);
1104 root_pass_list.at(1)->damage_rect = gfx::Rect(5, 5, 100, 100);
1106 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1107 root_pass_list.swap(root_frame_data->render_pass_list);
1109 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1110 root_frame->delegated_frame_data = root_frame_data.Pass();
1112 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
1113 SurfaceFactory::DrawCallback());
1115 scoped_ptr<CompositorFrame> aggregated_frame =
1116 aggregator_.Aggregate(root_surface_id_);
1118 ASSERT_TRUE(aggregated_frame);
1119 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1121 DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
1123 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1125 ASSERT_EQ(2u, aggregated_pass_list.size());
1127 // Damage rect for first aggregation should contain entire root surface.
1128 EXPECT_TRUE(
1129 aggregated_pass_list[1]->damage_rect.Contains(gfx::Rect(SurfaceSize())));
1132 AddPasses(&child_pass_list,
1133 gfx::Rect(SurfaceSize()),
1134 child_passes,
1135 arraysize(child_passes));
1137 RenderPass* child_root_pass = child_pass_list.at(0u);
1138 SharedQuadState* child_root_pass_sqs =
1139 child_root_pass->shared_quad_state_list.front();
1140 child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
1141 child_root_pass->damage_rect = gfx::Rect(10, 10, 10, 10);
1143 scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
1144 child_pass_list.swap(child_frame_data->render_pass_list);
1146 scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
1147 child_frame->delegated_frame_data = child_frame_data.Pass();
1149 factory_.SubmitFrame(child_surface_id, child_frame.Pass(),
1150 SurfaceFactory::DrawCallback());
1152 scoped_ptr<CompositorFrame> aggregated_frame =
1153 aggregator_.Aggregate(root_surface_id_);
1155 ASSERT_TRUE(aggregated_frame);
1156 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1158 DelegatedFrameData* frame_data =
1159 aggregated_frame->delegated_frame_data.get();
1161 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1163 ASSERT_EQ(2u, aggregated_pass_list.size());
1165 // Outer surface didn't change, so transformed inner damage rect should be
1166 // used.
1167 EXPECT_EQ(gfx::Rect(10, 20, 10, 10).ToString(),
1168 aggregated_pass_list[1]->damage_rect.ToString());
1172 RenderPassList root_pass_list;
1173 AddPasses(&root_pass_list,
1174 gfx::Rect(SurfaceSize()),
1175 root_passes,
1176 arraysize(root_passes));
1178 root_pass_list.at(0)
1179 ->shared_quad_state_list.front()
1180 ->content_to_target_transform.Translate(0, 10);
1181 root_pass_list.at(0)->damage_rect = gfx::Rect(0, 0, 1, 1);
1183 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1184 root_pass_list.swap(root_frame_data->render_pass_list);
1186 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1187 root_frame->delegated_frame_data = root_frame_data.Pass();
1189 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
1190 SurfaceFactory::DrawCallback());
1194 RenderPassList root_pass_list;
1195 AddPasses(&root_pass_list,
1196 gfx::Rect(SurfaceSize()),
1197 root_passes,
1198 arraysize(root_passes));
1200 root_pass_list.at(0)
1201 ->shared_quad_state_list.front()
1202 ->content_to_target_transform.Translate(0, 10);
1203 root_pass_list.at(0)->damage_rect = gfx::Rect(1, 1, 1, 1);
1205 scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1206 root_pass_list.swap(root_frame_data->render_pass_list);
1208 scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1209 root_frame->delegated_frame_data = root_frame_data.Pass();
1211 factory_.SubmitFrame(root_surface_id_, root_frame.Pass(),
1212 SurfaceFactory::DrawCallback());
1214 scoped_ptr<CompositorFrame> aggregated_frame =
1215 aggregator_.Aggregate(root_surface_id_);
1217 ASSERT_TRUE(aggregated_frame);
1218 ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1220 DelegatedFrameData* frame_data =
1221 aggregated_frame->delegated_frame_data.get();
1223 const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1225 ASSERT_EQ(2u, aggregated_pass_list.size());
1227 // The root surface was enqueued without being aggregated once, so it should
1228 // be treated as completely damaged.
1229 EXPECT_TRUE(aggregated_pass_list[1]->damage_rect.Contains(
1230 gfx::Rect(SurfaceSize())));
1233 factory_.Destroy(child_surface_id);
1236 class SurfaceAggregatorWithResourcesTest : public testing::Test {
1237 public:
1238 void SetUp() override {
1239 output_surface_ = FakeOutputSurface::CreateSoftware(
1240 make_scoped_ptr(new SoftwareOutputDevice));
1241 output_surface_->BindToClient(&output_surface_client_);
1242 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
1244 resource_provider_ = ResourceProvider::Create(output_surface_.get(),
1245 shared_bitmap_manager_.get(),
1246 NULL,
1247 NULL,
1249 false,
1252 aggregator_.reset(
1253 new SurfaceAggregator(&manager_, resource_provider_.get()));
1256 protected:
1257 SurfaceManager manager_;
1258 FakeOutputSurfaceClient output_surface_client_;
1259 scoped_ptr<OutputSurface> output_surface_;
1260 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
1261 scoped_ptr<ResourceProvider> resource_provider_;
1262 scoped_ptr<SurfaceAggregator> aggregator_;
1265 class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient {
1266 public:
1267 ResourceTrackingSurfaceFactoryClient() {}
1268 ~ResourceTrackingSurfaceFactoryClient() override {}
1270 void ReturnResources(const ReturnedResourceArray& resources) override {
1271 returned_resources_ = resources;
1274 ReturnedResourceArray returned_resources() const {
1275 return returned_resources_;
1278 private:
1279 ReturnedResourceArray returned_resources_;
1281 DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient);
1284 void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids,
1285 size_t num_resource_ids,
1286 SurfaceFactory* factory,
1287 SurfaceId surface_id) {
1288 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
1289 scoped_ptr<RenderPass> pass = RenderPass::Create();
1290 pass->id = RenderPassId(1, 1);
1291 SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
1292 for (size_t i = 0u; i < num_resource_ids; ++i) {
1293 TransferableResource resource;
1294 resource.id = resource_ids[i];
1295 resource.is_software = true;
1296 frame_data->resource_list.push_back(resource);
1297 TextureDrawQuad* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
1298 const gfx::Rect rect;
1299 const gfx::Rect opaque_rect;
1300 const gfx::Rect visible_rect;
1301 bool needs_blending = false;
1302 bool premultiplied_alpha = false;
1303 const gfx::PointF uv_top_left;
1304 const gfx::PointF uv_bottom_right;
1305 SkColor background_color = SK_ColorGREEN;
1306 const float vertex_opacity[4] = {0.f, 0.f, 1.f, 1.f};
1307 bool flipped = false;
1308 bool nearest_neighbor = false;
1309 quad->SetAll(sqs,
1310 rect,
1311 opaque_rect,
1312 visible_rect,
1313 needs_blending,
1314 resource_ids[i],
1315 premultiplied_alpha,
1316 uv_top_left,
1317 uv_bottom_right,
1318 background_color,
1319 vertex_opacity,
1320 flipped,
1321 nearest_neighbor);
1323 quad->shared_quad_state = sqs;
1325 frame_data->render_pass_list.push_back(pass.Pass());
1326 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
1327 frame->delegated_frame_data = frame_data.Pass();
1328 factory->SubmitFrame(surface_id, frame.Pass(),
1329 SurfaceFactory::DrawCallback());
1332 TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
1333 ResourceTrackingSurfaceFactoryClient client;
1334 SurfaceFactory factory(&manager_, &client);
1335 SurfaceId surface_id(7u);
1336 factory.Create(surface_id);
1338 ResourceProvider::ResourceId ids[] = {11, 12, 13};
1339 SubmitFrameWithResources(ids, arraysize(ids), &factory, surface_id);
1341 scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id);
1343 // Nothing should be available to be returned yet.
1344 EXPECT_TRUE(client.returned_resources().empty());
1346 SubmitFrameWithResources(NULL, 0u, &factory, surface_id);
1348 frame = aggregator_->Aggregate(surface_id);
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 factory.Destroy(surface_id);
1360 TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) {
1361 ResourceTrackingSurfaceFactoryClient client;
1362 SurfaceFactory factory(&manager_, &client);
1363 SurfaceId surface_id(7u);
1364 factory.Create(surface_id);
1366 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
1367 scoped_ptr<RenderPass> pass = RenderPass::Create();
1368 pass->id = RenderPassId(1, 1);
1369 TransferableResource resource;
1370 resource.id = 11;
1371 // ResourceProvider is software but resource is not, so it should be
1372 // ignored.
1373 resource.is_software = false;
1374 frame_data->resource_list.push_back(resource);
1375 frame_data->render_pass_list.push_back(pass.Pass());
1376 scoped_ptr<CompositorFrame> frame(new CompositorFrame);
1377 frame->delegated_frame_data = frame_data.Pass();
1378 factory.SubmitFrame(surface_id, frame.Pass(), SurfaceFactory::DrawCallback());
1380 scoped_ptr<CompositorFrame> returned_frame =
1381 aggregator_->Aggregate(surface_id);
1383 // Nothing should be available to be returned yet.
1384 EXPECT_TRUE(client.returned_resources().empty());
1386 SubmitFrameWithResources(NULL, 0u, &factory, surface_id);
1387 ASSERT_EQ(1u, client.returned_resources().size());
1388 EXPECT_EQ(11u, client.returned_resources()[0].id);
1390 factory.Destroy(surface_id);
1393 TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) {
1394 ResourceTrackingSurfaceFactoryClient client;
1395 SurfaceFactory factory(&manager_, &client);
1396 SurfaceId surface_id(7u);
1397 factory.Create(surface_id);
1398 SurfaceId surface_id2(8u);
1399 factory.Create(surface_id2);
1401 ResourceProvider::ResourceId ids[] = {11, 12, 13};
1402 SubmitFrameWithResources(ids, arraysize(ids), &factory, surface_id);
1403 ResourceProvider::ResourceId ids2[] = {14, 15, 16};
1404 SubmitFrameWithResources(ids2, arraysize(ids2), &factory, surface_id2);
1406 scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id);
1408 SubmitFrameWithResources(NULL, 0, &factory, surface_id);
1410 // Nothing should be available to be returned yet.
1411 EXPECT_TRUE(client.returned_resources().empty());
1413 frame = aggregator_->Aggregate(surface_id2);
1415 // surface_id wasn't referenced, so its resources should be returned.
1416 ASSERT_EQ(3u, client.returned_resources().size());
1417 ResourceProvider::ResourceId returned_ids[3];
1418 for (size_t i = 0; i < 3; ++i) {
1419 returned_ids[i] = client.returned_resources()[i].id;
1421 EXPECT_THAT(returned_ids,
1422 testing::WhenSorted(testing::ElementsAreArray(ids)));
1423 EXPECT_EQ(3u, resource_provider_->num_resources());
1424 factory.Destroy(surface_id);
1425 factory.Destroy(surface_id2);
1428 } // namespace
1429 } // namespace cc