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/fake_resource_provider.h"
23 #include "cc/test/render_pass_test_common.h"
24 #include "cc/test/render_pass_test_utils.h"
25 #include "cc/test/test_shared_bitmap_manager.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/skia/include/core/SkColor.h"
33 SurfaceId
InvalidSurfaceId() {
34 static SurfaceId invalid
;
35 invalid
.id
= static_cast<uint64_t>(-1);
39 gfx::Size
SurfaceSize() {
40 static gfx::Size
size(5, 5);
44 class EmptySurfaceFactoryClient
: public SurfaceFactoryClient
{
46 void ReturnResources(const ReturnedResourceArray
& resources
) override
{}
49 class SurfaceAggregatorTest
: public testing::Test
{
51 explicit SurfaceAggregatorTest(bool use_damage_rect
)
52 : factory_(&manager_
, &empty_client_
),
53 aggregator_(&manager_
, NULL
, use_damage_rect
) {}
55 SurfaceAggregatorTest() : SurfaceAggregatorTest(false) {}
58 SurfaceManager manager_
;
59 EmptySurfaceFactoryClient empty_client_
;
60 SurfaceFactory factory_
;
61 SurfaceAggregator aggregator_
;
64 TEST_F(SurfaceAggregatorTest
, ValidSurfaceNoFrame
) {
66 factory_
.Create(one_id
);
67 scoped_ptr
<CompositorFrame
> frame
= aggregator_
.Aggregate(one_id
);
69 factory_
.Destroy(one_id
);
72 class SurfaceAggregatorValidSurfaceTest
: public SurfaceAggregatorTest
{
74 explicit SurfaceAggregatorValidSurfaceTest(bool use_damage_rect
)
75 : SurfaceAggregatorTest(use_damage_rect
),
77 child_allocator_(2u) {}
78 SurfaceAggregatorValidSurfaceTest()
79 : SurfaceAggregatorValidSurfaceTest(false) {}
81 void SetUp() override
{
82 SurfaceAggregatorTest::SetUp();
83 root_surface_id_
= allocator_
.GenerateId();
84 factory_
.Create(root_surface_id_
);
87 void TearDown() override
{
88 factory_
.Destroy(root_surface_id_
);
89 SurfaceAggregatorTest::TearDown();
92 void AggregateAndVerify(test::Pass
* expected_passes
,
93 size_t expected_pass_count
,
94 SurfaceId
* surface_ids
,
95 size_t expected_surface_count
) {
96 scoped_ptr
<CompositorFrame
> aggregated_frame
=
97 aggregator_
.Aggregate(root_surface_id_
);
99 ASSERT_TRUE(aggregated_frame
);
100 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
102 DelegatedFrameData
* frame_data
=
103 aggregated_frame
->delegated_frame_data
.get();
105 TestPassesMatchExpectations(
106 expected_passes
, expected_pass_count
, &frame_data
->render_pass_list
);
108 // Ensure no duplicate pass ids output.
109 std::set
<RenderPassId
> used_passes
;
110 for (auto* pass
: frame_data
->render_pass_list
) {
111 EXPECT_TRUE(used_passes
.insert(pass
->id
).second
);
114 EXPECT_EQ(expected_surface_count
,
115 aggregator_
.previous_contained_surfaces().size());
116 for (size_t i
= 0; i
< expected_surface_count
; i
++) {
118 aggregator_
.previous_contained_surfaces().find(surface_ids
[i
]) !=
119 aggregator_
.previous_contained_surfaces().end());
123 void SubmitPassListAsFrame(SurfaceId surface_id
, RenderPassList
* pass_list
) {
124 scoped_ptr
<DelegatedFrameData
> frame_data(new DelegatedFrameData
);
125 pass_list
->swap(frame_data
->render_pass_list
);
127 scoped_ptr
<CompositorFrame
> frame(new CompositorFrame
);
128 frame
->delegated_frame_data
= frame_data
.Pass();
130 factory_
.SubmitFrame(surface_id
, frame
.Pass(),
131 SurfaceFactory::DrawCallback());
134 void SubmitFrame(test::Pass
* passes
,
136 SurfaceId surface_id
) {
137 RenderPassList pass_list
;
138 AddPasses(&pass_list
, gfx::Rect(SurfaceSize()), passes
, pass_count
);
139 SubmitPassListAsFrame(surface_id
, &pass_list
);
142 void QueuePassAsFrame(scoped_ptr
<RenderPass
> pass
, SurfaceId surface_id
) {
143 scoped_ptr
<DelegatedFrameData
> delegated_frame_data(new DelegatedFrameData
);
144 delegated_frame_data
->render_pass_list
.push_back(pass
.Pass());
146 scoped_ptr
<CompositorFrame
> child_frame(new CompositorFrame
);
147 child_frame
->delegated_frame_data
= delegated_frame_data
.Pass();
149 factory_
.SubmitFrame(surface_id
, child_frame
.Pass(),
150 SurfaceFactory::DrawCallback());
154 SurfaceId root_surface_id_
;
155 SurfaceIdAllocator allocator_
;
156 SurfaceIdAllocator child_allocator_
;
159 // Tests that a very simple frame containing only two solid color quads makes it
160 // through the aggregator correctly.
161 TEST_F(SurfaceAggregatorValidSurfaceTest
, SimpleFrame
) {
162 test::Quad quads
[] = {test::Quad::SolidColorQuad(SK_ColorRED
),
163 test::Quad::SolidColorQuad(SK_ColorBLUE
)};
164 test::Pass passes
[] = {test::Pass(quads
, arraysize(quads
))};
166 SubmitFrame(passes
, arraysize(passes
), root_surface_id_
);
168 SurfaceId ids
[] = {root_surface_id_
};
169 AggregateAndVerify(passes
, arraysize(passes
), ids
, arraysize(ids
));
172 TEST_F(SurfaceAggregatorValidSurfaceTest
, OpacityCopied
) {
173 SurfaceId embedded_surface_id
= allocator_
.GenerateId();
174 factory_
.Create(embedded_surface_id
);
176 test::Quad embedded_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
),
177 test::Quad::SolidColorQuad(SK_ColorBLUE
)};
178 test::Pass embedded_passes
[] = {
179 test::Pass(embedded_quads
, arraysize(embedded_quads
))};
181 SubmitFrame(embedded_passes
, arraysize(embedded_passes
), embedded_surface_id
);
183 test::Quad quads
[] = {test::Quad::SurfaceQuad(embedded_surface_id
, .5f
)};
184 test::Pass passes
[] = {test::Pass(quads
, arraysize(quads
))};
186 SubmitFrame(passes
, arraysize(passes
), root_surface_id_
);
188 scoped_ptr
<CompositorFrame
> aggregated_frame
=
189 aggregator_
.Aggregate(root_surface_id_
);
191 ASSERT_TRUE(aggregated_frame
);
192 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
194 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
196 RenderPassList
& render_pass_list(frame_data
->render_pass_list
);
197 ASSERT_EQ(2u, render_pass_list
.size());
198 SharedQuadStateList
& shared_quad_state_list(
199 render_pass_list
[0]->shared_quad_state_list
);
200 ASSERT_EQ(2u, shared_quad_state_list
.size());
201 EXPECT_EQ(1.f
, shared_quad_state_list
.ElementAt(0)->opacity
);
202 EXPECT_EQ(1.f
, shared_quad_state_list
.ElementAt(1)->opacity
);
204 SharedQuadStateList
& shared_quad_state_list2(
205 render_pass_list
[1]->shared_quad_state_list
);
206 ASSERT_EQ(1u, shared_quad_state_list2
.size());
207 EXPECT_EQ(.5f
, shared_quad_state_list2
.ElementAt(0)->opacity
);
209 factory_
.Destroy(embedded_surface_id
);
212 TEST_F(SurfaceAggregatorValidSurfaceTest
, MultiPassSimpleFrame
) {
213 test::Quad quads
[][2] = {{test::Quad::SolidColorQuad(SK_ColorWHITE
),
214 test::Quad::SolidColorQuad(SK_ColorLTGRAY
)},
215 {test::Quad::SolidColorQuad(SK_ColorGRAY
),
216 test::Quad::SolidColorQuad(SK_ColorDKGRAY
)}};
217 test::Pass passes
[] = {
218 test::Pass(quads
[0], arraysize(quads
[0]), RenderPassId(1, 1)),
219 test::Pass(quads
[1], arraysize(quads
[1]), RenderPassId(1, 2))};
221 SubmitFrame(passes
, arraysize(passes
), root_surface_id_
);
223 SurfaceId ids
[] = {root_surface_id_
};
224 AggregateAndVerify(passes
, arraysize(passes
), ids
, arraysize(ids
));
227 // This tests very simple embedding. root_surface has a frame containing a few
228 // solid color quads and a surface quad referencing embedded_surface.
229 // embedded_surface has a frame containing only a solid color quad. The solid
230 // color quad should be aggregated into the final frame.
231 TEST_F(SurfaceAggregatorValidSurfaceTest
, SimpleSurfaceReference
) {
232 SurfaceId embedded_surface_id
= allocator_
.GenerateId();
233 factory_
.Create(embedded_surface_id
);
235 test::Quad embedded_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
)};
236 test::Pass embedded_passes
[] = {
237 test::Pass(embedded_quads
, arraysize(embedded_quads
))};
239 SubmitFrame(embedded_passes
, arraysize(embedded_passes
), embedded_surface_id
);
241 test::Quad root_quads
[] = {test::Quad::SolidColorQuad(SK_ColorWHITE
),
242 test::Quad::SurfaceQuad(embedded_surface_id
, 1.f
),
243 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
244 test::Pass root_passes
[] = {test::Pass(root_quads
, arraysize(root_quads
))};
246 SubmitFrame(root_passes
, arraysize(root_passes
), root_surface_id_
);
248 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorWHITE
),
249 test::Quad::SolidColorQuad(SK_ColorGREEN
),
250 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
251 test::Pass expected_passes
[] = {
252 test::Pass(expected_quads
, arraysize(expected_quads
))};
253 SurfaceId ids
[] = {root_surface_id_
, embedded_surface_id
};
255 expected_passes
, arraysize(expected_passes
), ids
, arraysize(ids
));
257 factory_
.Destroy(embedded_surface_id
);
260 TEST_F(SurfaceAggregatorValidSurfaceTest
, CopyRequest
) {
261 SurfaceId embedded_surface_id
= allocator_
.GenerateId();
262 factory_
.Create(embedded_surface_id
);
264 test::Quad embedded_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
)};
265 test::Pass embedded_passes
[] = {
266 test::Pass(embedded_quads
, arraysize(embedded_quads
))};
268 SubmitFrame(embedded_passes
, arraysize(embedded_passes
), embedded_surface_id
);
269 scoped_ptr
<CopyOutputRequest
> copy_request(
270 CopyOutputRequest::CreateEmptyRequest());
271 CopyOutputRequest
* copy_request_ptr
= copy_request
.get();
272 factory_
.RequestCopyOfSurface(embedded_surface_id
, copy_request
.Pass());
274 test::Quad root_quads
[] = {test::Quad::SolidColorQuad(SK_ColorWHITE
),
275 test::Quad::SurfaceQuad(embedded_surface_id
, 1.f
),
276 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
277 test::Pass root_passes
[] = {test::Pass(root_quads
, arraysize(root_quads
))};
279 SubmitFrame(root_passes
, arraysize(root_passes
), root_surface_id_
);
281 scoped_ptr
<CompositorFrame
> aggregated_frame
=
282 aggregator_
.Aggregate(root_surface_id_
);
284 ASSERT_TRUE(aggregated_frame
);
285 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
287 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
289 test::Quad expected_quads
[] = {
290 test::Quad::SolidColorQuad(SK_ColorWHITE
),
291 test::Quad::RenderPassQuad(frame_data
->render_pass_list
[0]->id
),
292 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
293 test::Pass expected_passes
[] = {
294 test::Pass(embedded_quads
, arraysize(embedded_quads
)),
295 test::Pass(expected_quads
, arraysize(expected_quads
))};
296 TestPassesMatchExpectations(expected_passes
,
297 arraysize(expected_passes
),
298 &frame_data
->render_pass_list
);
299 ASSERT_EQ(2u, frame_data
->render_pass_list
.size());
300 ASSERT_EQ(1u, frame_data
->render_pass_list
[0]->copy_requests
.size());
301 DCHECK_EQ(copy_request_ptr
,
302 frame_data
->render_pass_list
[0]->copy_requests
[0]);
304 SurfaceId surface_ids
[] = {root_surface_id_
, embedded_surface_id
};
305 EXPECT_EQ(arraysize(surface_ids
),
306 aggregator_
.previous_contained_surfaces().size());
307 for (size_t i
= 0; i
< arraysize(surface_ids
); i
++) {
309 aggregator_
.previous_contained_surfaces().find(surface_ids
[i
]) !=
310 aggregator_
.previous_contained_surfaces().end());
313 factory_
.Destroy(embedded_surface_id
);
316 // Root surface may contain copy requests.
317 TEST_F(SurfaceAggregatorValidSurfaceTest
, RootCopyRequest
) {
318 SurfaceId embedded_surface_id
= allocator_
.GenerateId();
319 factory_
.Create(embedded_surface_id
);
321 test::Quad embedded_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
)};
322 test::Pass embedded_passes
[] = {
323 test::Pass(embedded_quads
, arraysize(embedded_quads
))};
325 SubmitFrame(embedded_passes
, arraysize(embedded_passes
), embedded_surface_id
);
326 scoped_ptr
<CopyOutputRequest
> copy_request(
327 CopyOutputRequest::CreateEmptyRequest());
328 CopyOutputRequest
* copy_request_ptr
= copy_request
.get();
329 scoped_ptr
<CopyOutputRequest
> copy_request2(
330 CopyOutputRequest::CreateEmptyRequest());
331 CopyOutputRequest
* copy_request2_ptr
= copy_request2
.get();
333 test::Quad root_quads
[] = {test::Quad::SolidColorQuad(SK_ColorWHITE
),
334 test::Quad::SurfaceQuad(embedded_surface_id
, 1.f
),
335 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
336 test::Quad root_quads2
[] = {test::Quad::SolidColorQuad(SK_ColorRED
)};
337 test::Pass root_passes
[] = {
338 test::Pass(root_quads
, arraysize(root_quads
), RenderPassId(1, 1)),
339 test::Pass(root_quads2
, arraysize(root_quads2
), RenderPassId(1, 2))};
341 RenderPassList pass_list
;
342 AddPasses(&pass_list
,
343 gfx::Rect(SurfaceSize()),
345 arraysize(root_passes
));
346 pass_list
[0]->copy_requests
.push_back(copy_request
.Pass());
347 pass_list
[1]->copy_requests
.push_back(copy_request2
.Pass());
349 scoped_ptr
<DelegatedFrameData
> frame_data(new DelegatedFrameData
);
350 pass_list
.swap(frame_data
->render_pass_list
);
352 scoped_ptr
<CompositorFrame
> frame(new CompositorFrame
);
353 frame
->delegated_frame_data
= frame_data
.Pass();
355 factory_
.SubmitFrame(root_surface_id_
, frame
.Pass(),
356 SurfaceFactory::DrawCallback());
359 scoped_ptr
<CompositorFrame
> aggregated_frame
=
360 aggregator_
.Aggregate(root_surface_id_
);
362 ASSERT_TRUE(aggregated_frame
);
363 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
365 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
367 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorWHITE
),
368 test::Quad::SolidColorQuad(SK_ColorGREEN
),
369 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
370 test::Pass expected_passes
[] = {
371 test::Pass(expected_quads
, arraysize(expected_quads
)),
372 test::Pass(root_quads2
, arraysize(root_quads2
))};
373 TestPassesMatchExpectations(expected_passes
,
374 arraysize(expected_passes
),
375 &frame_data
->render_pass_list
);
376 ASSERT_EQ(2u, frame_data
->render_pass_list
.size());
377 ASSERT_EQ(1u, frame_data
->render_pass_list
[0]->copy_requests
.size());
378 DCHECK_EQ(copy_request_ptr
,
379 frame_data
->render_pass_list
[0]->copy_requests
[0]);
380 ASSERT_EQ(1u, frame_data
->render_pass_list
[1]->copy_requests
.size());
381 DCHECK_EQ(copy_request2_ptr
,
382 frame_data
->render_pass_list
[1]->copy_requests
[0]);
384 SurfaceId surface_ids
[] = {root_surface_id_
, embedded_surface_id
};
385 EXPECT_EQ(arraysize(surface_ids
),
386 aggregator_
.previous_contained_surfaces().size());
387 for (size_t i
= 0; i
< arraysize(surface_ids
); i
++) {
389 aggregator_
.previous_contained_surfaces().find(surface_ids
[i
]) !=
390 aggregator_
.previous_contained_surfaces().end());
393 // Ensure copy requests have been removed from root surface.
394 const CompositorFrame
* original_frame
=
395 manager_
.GetSurfaceForId(root_surface_id_
)->GetEligibleFrame();
396 RenderPassList
& original_pass_list
=
397 original_frame
->delegated_frame_data
->render_pass_list
;
398 ASSERT_EQ(2u, original_pass_list
.size());
399 DCHECK(original_pass_list
[0]->copy_requests
.empty());
400 DCHECK(original_pass_list
[1]->copy_requests
.empty());
402 factory_
.Destroy(embedded_surface_id
);
405 // This tests referencing a surface that has multiple render passes.
406 TEST_F(SurfaceAggregatorValidSurfaceTest
, MultiPassSurfaceReference
) {
407 SurfaceId embedded_surface_id
= child_allocator_
.GenerateId();
408 factory_
.Create(embedded_surface_id
);
410 RenderPassId pass_ids
[] = {RenderPassId(1, 1), RenderPassId(1, 2),
413 test::Quad embedded_quads
[][2] = {
414 {test::Quad::SolidColorQuad(1), test::Quad::SolidColorQuad(2)},
415 {test::Quad::SolidColorQuad(3), test::Quad::RenderPassQuad(pass_ids
[0])},
416 {test::Quad::SolidColorQuad(4), test::Quad::RenderPassQuad(pass_ids
[1])}};
417 test::Pass embedded_passes
[] = {
418 test::Pass(embedded_quads
[0], arraysize(embedded_quads
[0]), pass_ids
[0]),
419 test::Pass(embedded_quads
[1], arraysize(embedded_quads
[1]), pass_ids
[1]),
420 test::Pass(embedded_quads
[2], arraysize(embedded_quads
[2]), pass_ids
[2])};
422 SubmitFrame(embedded_passes
, arraysize(embedded_passes
), embedded_surface_id
);
424 test::Quad root_quads
[][2] = {
425 {test::Quad::SolidColorQuad(5), test::Quad::SolidColorQuad(6)},
426 {test::Quad::SurfaceQuad(embedded_surface_id
, 1.f
),
427 test::Quad::RenderPassQuad(pass_ids
[0])},
428 {test::Quad::SolidColorQuad(7), test::Quad::RenderPassQuad(pass_ids
[1])}};
429 test::Pass root_passes
[] = {
430 test::Pass(root_quads
[0], arraysize(root_quads
[0]), pass_ids
[0]),
431 test::Pass(root_quads
[1], arraysize(root_quads
[1]), pass_ids
[1]),
432 test::Pass(root_quads
[2], arraysize(root_quads
[2]), pass_ids
[2])};
434 SubmitFrame(root_passes
, arraysize(root_passes
), root_surface_id_
);
436 scoped_ptr
<CompositorFrame
> aggregated_frame
=
437 aggregator_
.Aggregate(root_surface_id_
);
439 ASSERT_TRUE(aggregated_frame
);
440 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
442 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
444 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
446 ASSERT_EQ(5u, aggregated_pass_list
.size());
447 RenderPassId actual_pass_ids
[] = {
448 aggregated_pass_list
[0]->id
, aggregated_pass_list
[1]->id
,
449 aggregated_pass_list
[2]->id
, aggregated_pass_list
[3]->id
,
450 aggregated_pass_list
[4]->id
};
451 for (size_t i
= 0; i
< 5; ++i
) {
452 for (size_t j
= 0; j
< i
; ++j
) {
453 EXPECT_NE(actual_pass_ids
[i
], actual_pass_ids
[j
]);
458 SCOPED_TRACE("First pass");
459 // The first pass will just be the first pass from the root surfaces quad
460 // with no render pass quads to remap.
461 TestPassMatchesExpectations(root_passes
[0], aggregated_pass_list
[0]);
465 SCOPED_TRACE("Second pass");
466 // The next two passes will be from the embedded surface since we have to
467 // draw those passes before they are referenced from the render pass draw
468 // quad embedded into the root surface's second pass.
469 // First, there's the first embedded pass which doesn't reference anything
471 TestPassMatchesExpectations(embedded_passes
[0], aggregated_pass_list
[1]);
475 SCOPED_TRACE("Third pass");
476 const QuadList
& third_pass_quad_list
= aggregated_pass_list
[2]->quad_list
;
477 ASSERT_EQ(2u, third_pass_quad_list
.size());
478 TestQuadMatchesExpectations(embedded_quads
[1][0],
479 third_pass_quad_list
.ElementAt(0));
481 // This render pass pass quad will reference the first pass from the
482 // embedded surface, which is the second pass in the aggregated frame.
483 ASSERT_EQ(DrawQuad::RENDER_PASS
,
484 third_pass_quad_list
.ElementAt(1)->material
);
485 const RenderPassDrawQuad
* third_pass_render_pass_draw_quad
=
486 RenderPassDrawQuad::MaterialCast(third_pass_quad_list
.ElementAt(1));
487 EXPECT_EQ(actual_pass_ids
[1],
488 third_pass_render_pass_draw_quad
->render_pass_id
);
492 SCOPED_TRACE("Fourth pass");
493 // The fourth pass will have aggregated quads from the root surface's second
494 // pass and the embedded surface's first pass.
495 const QuadList
& fourth_pass_quad_list
= aggregated_pass_list
[3]->quad_list
;
496 ASSERT_EQ(3u, fourth_pass_quad_list
.size());
498 // The first quad will be the yellow quad from the embedded surface's last
500 TestQuadMatchesExpectations(embedded_quads
[2][0],
501 fourth_pass_quad_list
.ElementAt(0));
503 // The next quad will be a render pass quad referencing the second pass from
504 // the embedded surface, which is the third pass in the aggregated frame.
505 ASSERT_EQ(DrawQuad::RENDER_PASS
,
506 fourth_pass_quad_list
.ElementAt(1)->material
);
507 const RenderPassDrawQuad
* fourth_pass_first_render_pass_draw_quad
=
508 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list
.ElementAt(1));
509 EXPECT_EQ(actual_pass_ids
[2],
510 fourth_pass_first_render_pass_draw_quad
->render_pass_id
);
512 // The last quad will be a render pass quad referencing the first pass from
513 // the root surface, which is the first pass overall.
514 ASSERT_EQ(DrawQuad::RENDER_PASS
,
515 fourth_pass_quad_list
.ElementAt(2)->material
);
516 const RenderPassDrawQuad
* fourth_pass_second_render_pass_draw_quad
=
517 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list
.ElementAt(2));
518 EXPECT_EQ(actual_pass_ids
[0],
519 fourth_pass_second_render_pass_draw_quad
->render_pass_id
);
523 SCOPED_TRACE("Fifth pass");
524 const QuadList
& fifth_pass_quad_list
= aggregated_pass_list
[4]->quad_list
;
525 ASSERT_EQ(2u, fifth_pass_quad_list
.size());
527 TestQuadMatchesExpectations(root_quads
[2][0],
528 fifth_pass_quad_list
.ElementAt(0));
530 // The last quad in the last pass will reference the second pass from the
531 // root surface, which after aggregating is the fourth pass in the overall
533 ASSERT_EQ(DrawQuad::RENDER_PASS
,
534 fifth_pass_quad_list
.ElementAt(1)->material
);
535 const RenderPassDrawQuad
* fifth_pass_render_pass_draw_quad
=
536 RenderPassDrawQuad::MaterialCast(fifth_pass_quad_list
.ElementAt(1));
537 EXPECT_EQ(actual_pass_ids
[3],
538 fifth_pass_render_pass_draw_quad
->render_pass_id
);
540 factory_
.Destroy(embedded_surface_id
);
543 // Tests an invalid surface reference in a frame. The surface quad should just
545 TEST_F(SurfaceAggregatorValidSurfaceTest
, InvalidSurfaceReference
) {
546 test::Quad quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
),
547 test::Quad::SurfaceQuad(InvalidSurfaceId(), 1.f
),
548 test::Quad::SolidColorQuad(SK_ColorBLUE
)};
549 test::Pass passes
[] = {test::Pass(quads
, arraysize(quads
))};
551 SubmitFrame(passes
, arraysize(passes
), root_surface_id_
);
553 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
),
554 test::Quad::SolidColorQuad(SK_ColorBLUE
)};
555 test::Pass expected_passes
[] = {
556 test::Pass(expected_quads
, arraysize(expected_quads
))};
557 SurfaceId ids
[] = {root_surface_id_
, InvalidSurfaceId()};
559 expected_passes
, arraysize(expected_passes
), ids
, arraysize(ids
));
562 // Tests a reference to a valid surface with no submitted frame. This quad
563 // should also just be dropped.
564 TEST_F(SurfaceAggregatorValidSurfaceTest
, ValidSurfaceReferenceWithNoFrame
) {
565 SurfaceId surface_with_no_frame_id
= allocator_
.GenerateId();
566 factory_
.Create(surface_with_no_frame_id
);
567 test::Quad quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
),
568 test::Quad::SurfaceQuad(surface_with_no_frame_id
, 1.f
),
569 test::Quad::SolidColorQuad(SK_ColorBLUE
)};
570 test::Pass passes
[] = {test::Pass(quads
, arraysize(quads
))};
572 SubmitFrame(passes
, arraysize(passes
), root_surface_id_
);
574 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
),
575 test::Quad::SolidColorQuad(SK_ColorBLUE
)};
576 test::Pass expected_passes
[] = {
577 test::Pass(expected_quads
, arraysize(expected_quads
))};
578 SurfaceId ids
[] = {root_surface_id_
, surface_with_no_frame_id
};
580 expected_passes
, arraysize(expected_passes
), ids
, arraysize(ids
));
581 factory_
.Destroy(surface_with_no_frame_id
);
584 // Tests a surface quad referencing itself, generating a trivial cycle.
585 // The quad creating the cycle should be dropped from the final frame.
586 TEST_F(SurfaceAggregatorValidSurfaceTest
, SimpleCyclicalReference
) {
587 test::Quad quads
[] = {test::Quad::SurfaceQuad(root_surface_id_
, 1.f
),
588 test::Quad::SolidColorQuad(SK_ColorYELLOW
)};
589 test::Pass passes
[] = {test::Pass(quads
, arraysize(quads
))};
591 SubmitFrame(passes
, arraysize(passes
), root_surface_id_
);
593 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorYELLOW
)};
594 test::Pass expected_passes
[] = {
595 test::Pass(expected_quads
, arraysize(expected_quads
))};
596 SurfaceId ids
[] = {root_surface_id_
};
598 expected_passes
, arraysize(expected_passes
), ids
, arraysize(ids
));
601 // Tests a more complex cycle with one intermediate surface.
602 TEST_F(SurfaceAggregatorValidSurfaceTest
, TwoSurfaceCyclicalReference
) {
603 SurfaceId child_surface_id
= allocator_
.GenerateId();
604 factory_
.Create(child_surface_id
);
606 test::Quad parent_quads
[] = {test::Quad::SolidColorQuad(SK_ColorBLUE
),
607 test::Quad::SurfaceQuad(child_surface_id
, 1.f
),
608 test::Quad::SolidColorQuad(SK_ColorCYAN
)};
609 test::Pass parent_passes
[] = {
610 test::Pass(parent_quads
, arraysize(parent_quads
))};
612 SubmitFrame(parent_passes
, arraysize(parent_passes
), root_surface_id_
);
614 test::Quad child_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
),
615 test::Quad::SurfaceQuad(root_surface_id_
, 1.f
),
616 test::Quad::SolidColorQuad(SK_ColorMAGENTA
)};
617 test::Pass child_passes
[] = {test::Pass(child_quads
, arraysize(child_quads
))};
619 SubmitFrame(child_passes
, arraysize(child_passes
), child_surface_id
);
621 // The child surface's reference to the root_surface_ will be dropped, so
622 // we'll end up with:
623 // SK_ColorBLUE from the parent
624 // SK_ColorGREEN from the child
625 // SK_ColorMAGENTA from the child
626 // SK_ColorCYAN from the parent
627 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorBLUE
),
628 test::Quad::SolidColorQuad(SK_ColorGREEN
),
629 test::Quad::SolidColorQuad(SK_ColorMAGENTA
),
630 test::Quad::SolidColorQuad(SK_ColorCYAN
)};
631 test::Pass expected_passes
[] = {
632 test::Pass(expected_quads
, arraysize(expected_quads
))};
633 SurfaceId ids
[] = {root_surface_id_
, child_surface_id
};
635 expected_passes
, arraysize(expected_passes
), ids
, arraysize(ids
));
636 factory_
.Destroy(child_surface_id
);
639 // Tests that we map render pass IDs from different surfaces into a unified
640 // namespace and update RenderPassDrawQuad's id references to match.
641 TEST_F(SurfaceAggregatorValidSurfaceTest
, RenderPassIdMapping
) {
642 SurfaceId child_surface_id
= allocator_
.GenerateId();
643 factory_
.Create(child_surface_id
);
645 RenderPassId child_pass_id
[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
646 test::Quad child_quad
[][1] = {{test::Quad::SolidColorQuad(SK_ColorGREEN
)},
647 {test::Quad::RenderPassQuad(child_pass_id
[0])}};
648 test::Pass surface_passes
[] = {
649 test::Pass(child_quad
[0], arraysize(child_quad
[0]), child_pass_id
[0]),
650 test::Pass(child_quad
[1], arraysize(child_quad
[1]), child_pass_id
[1])};
652 SubmitFrame(surface_passes
, arraysize(surface_passes
), child_surface_id
);
654 // Pass IDs from the parent surface may collide with ones from the child.
655 RenderPassId parent_pass_id
[] = {RenderPassId(2, 1), RenderPassId(1, 2)};
656 test::Quad parent_quad
[][1] = {
657 {test::Quad::SurfaceQuad(child_surface_id
, 1.f
)},
658 {test::Quad::RenderPassQuad(parent_pass_id
[0])}};
659 test::Pass parent_passes
[] = {
660 test::Pass(parent_quad
[0], arraysize(parent_quad
[0]), parent_pass_id
[0]),
661 test::Pass(parent_quad
[1], arraysize(parent_quad
[1]), parent_pass_id
[1])};
663 SubmitFrame(parent_passes
, arraysize(parent_passes
), root_surface_id_
);
664 scoped_ptr
<CompositorFrame
> aggregated_frame
=
665 aggregator_
.Aggregate(root_surface_id_
);
667 ASSERT_TRUE(aggregated_frame
);
668 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
670 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
672 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
674 ASSERT_EQ(3u, aggregated_pass_list
.size());
675 RenderPassId actual_pass_ids
[] = {aggregated_pass_list
[0]->id
,
676 aggregated_pass_list
[1]->id
,
677 aggregated_pass_list
[2]->id
};
678 // Make sure the aggregated frame's pass IDs are all unique.
679 for (size_t i
= 0; i
< 3; ++i
) {
680 for (size_t j
= 0; j
< i
; ++j
) {
681 EXPECT_NE(actual_pass_ids
[j
], actual_pass_ids
[i
]) << "pass ids " << i
686 // Make sure the render pass quads reference the remapped pass IDs.
687 DrawQuad
* render_pass_quads
[] = {aggregated_pass_list
[1]->quad_list
.front(),
688 aggregated_pass_list
[2]->quad_list
.front()};
689 ASSERT_EQ(render_pass_quads
[0]->material
, DrawQuad::RENDER_PASS
);
692 RenderPassDrawQuad::MaterialCast(render_pass_quads
[0])->render_pass_id
);
694 ASSERT_EQ(render_pass_quads
[1]->material
, DrawQuad::RENDER_PASS
);
697 RenderPassDrawQuad::MaterialCast(render_pass_quads
[1])->render_pass_id
);
698 factory_
.Destroy(child_surface_id
);
701 void AddSolidColorQuadWithBlendMode(const gfx::Size
& size
,
703 const SkXfermode::Mode blend_mode
) {
704 const gfx::Transform layer_to_target_transform
;
705 const gfx::Size
layer_bounds(size
);
706 const gfx::Rect
visible_layer_rect(size
);
707 const gfx::Rect
clip_rect(size
);
709 bool is_clipped
= false;
712 bool force_anti_aliasing_off
= false;
713 SharedQuadState
* sqs
= pass
->CreateAndAppendSharedQuadState();
714 sqs
->SetAll(layer_to_target_transform
, layer_bounds
, visible_layer_rect
,
715 clip_rect
, is_clipped
, opacity
, blend_mode
, 0);
717 SolidColorDrawQuad
* color_quad
=
718 pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
719 color_quad
->SetNew(pass
->shared_quad_state_list
.back(), visible_layer_rect
,
720 visible_layer_rect
, SK_ColorGREEN
,
721 force_anti_aliasing_off
);
724 // This tests that we update shared quad state pointers correctly within
725 // aggregated passes. The shared quad state list on the aggregated pass will
726 // include the shared quad states from each pass in one list so the quads will
727 // end up pointed to shared quad state objects at different offsets. This test
728 // uses the blend_mode value stored on the shared quad state to track the shared
729 // quad state, but anything saved on the shared quad state would work.
731 // This test has 4 surfaces in the following structure:
732 // root_surface -> quad with kClear_Mode,
733 // [child_one_surface],
734 // quad with kDstOver_Mode,
735 // [child_two_surface],
736 // quad with kDstIn_Mode
737 // child_one_surface -> quad with kSrc_Mode,
738 // [grandchild_surface],
739 // quad with kSrcOver_Mode
740 // child_two_surface -> quad with kSrcIn_Mode
741 // grandchild_surface -> quad with kDst_Mode
743 // Resulting in the following aggregated pass:
744 // quad_root_0 - blend_mode kClear_Mode
745 // quad_child_one_0 - blend_mode kSrc_Mode
746 // quad_grandchild_0 - blend_mode kDst_Mode
747 // quad_child_one_1 - blend_mode kSrcOver_Mode
748 // quad_root_1 - blend_mode kDstOver_Mode
749 // quad_child_two_0 - blend_mode kSrcIn_Mode
750 // quad_root_2 - blend_mode kDstIn_Mode
751 TEST_F(SurfaceAggregatorValidSurfaceTest
, AggregateSharedQuadStateProperties
) {
752 const SkXfermode::Mode blend_modes
[] = {SkXfermode::kClear_Mode
, // 0
753 SkXfermode::kSrc_Mode
, // 1
754 SkXfermode::kDst_Mode
, // 2
755 SkXfermode::kSrcOver_Mode
, // 3
756 SkXfermode::kDstOver_Mode
, // 4
757 SkXfermode::kSrcIn_Mode
, // 5
758 SkXfermode::kDstIn_Mode
, // 6
761 RenderPassId
pass_id(1, 1);
762 SurfaceId grandchild_surface_id
= allocator_
.GenerateId();
763 factory_
.Create(grandchild_surface_id
);
764 scoped_ptr
<RenderPass
> grandchild_pass
= RenderPass::Create();
765 gfx::Rect
output_rect(SurfaceSize());
766 gfx::Rect
damage_rect(SurfaceSize());
767 gfx::Transform transform_to_root_target
;
768 grandchild_pass
->SetNew(
769 pass_id
, output_rect
, damage_rect
, transform_to_root_target
);
770 AddSolidColorQuadWithBlendMode(
771 SurfaceSize(), grandchild_pass
.get(), blend_modes
[2]);
772 QueuePassAsFrame(grandchild_pass
.Pass(), grandchild_surface_id
);
774 SurfaceId child_one_surface_id
= allocator_
.GenerateId();
775 factory_
.Create(child_one_surface_id
);
777 scoped_ptr
<RenderPass
> child_one_pass
= RenderPass::Create();
778 child_one_pass
->SetNew(
779 pass_id
, output_rect
, damage_rect
, transform_to_root_target
);
780 AddSolidColorQuadWithBlendMode(
781 SurfaceSize(), child_one_pass
.get(), blend_modes
[1]);
782 SurfaceDrawQuad
* grandchild_surface_quad
=
783 child_one_pass
->CreateAndAppendDrawQuad
<SurfaceDrawQuad
>();
784 grandchild_surface_quad
->SetNew(child_one_pass
->shared_quad_state_list
.back(),
785 gfx::Rect(SurfaceSize()),
786 gfx::Rect(SurfaceSize()),
787 grandchild_surface_id
);
788 AddSolidColorQuadWithBlendMode(
789 SurfaceSize(), child_one_pass
.get(), blend_modes
[3]);
790 QueuePassAsFrame(child_one_pass
.Pass(), child_one_surface_id
);
792 SurfaceId child_two_surface_id
= allocator_
.GenerateId();
793 factory_
.Create(child_two_surface_id
);
795 scoped_ptr
<RenderPass
> child_two_pass
= RenderPass::Create();
796 child_two_pass
->SetNew(
797 pass_id
, output_rect
, damage_rect
, transform_to_root_target
);
798 AddSolidColorQuadWithBlendMode(
799 SurfaceSize(), child_two_pass
.get(), blend_modes
[5]);
800 QueuePassAsFrame(child_two_pass
.Pass(), child_two_surface_id
);
802 scoped_ptr
<RenderPass
> root_pass
= RenderPass::Create();
804 pass_id
, output_rect
, damage_rect
, transform_to_root_target
);
806 AddSolidColorQuadWithBlendMode(
807 SurfaceSize(), root_pass
.get(), blend_modes
[0]);
808 SurfaceDrawQuad
* child_one_surface_quad
=
809 root_pass
->CreateAndAppendDrawQuad
<SurfaceDrawQuad
>();
810 child_one_surface_quad
->SetNew(root_pass
->shared_quad_state_list
.back(),
811 gfx::Rect(SurfaceSize()),
812 gfx::Rect(SurfaceSize()),
813 child_one_surface_id
);
814 AddSolidColorQuadWithBlendMode(
815 SurfaceSize(), root_pass
.get(), blend_modes
[4]);
816 SurfaceDrawQuad
* child_two_surface_quad
=
817 root_pass
->CreateAndAppendDrawQuad
<SurfaceDrawQuad
>();
818 child_two_surface_quad
->SetNew(root_pass
->shared_quad_state_list
.back(),
819 gfx::Rect(SurfaceSize()),
820 gfx::Rect(SurfaceSize()),
821 child_two_surface_id
);
822 AddSolidColorQuadWithBlendMode(
823 SurfaceSize(), root_pass
.get(), blend_modes
[6]);
825 QueuePassAsFrame(root_pass
.Pass(), root_surface_id_
);
827 scoped_ptr
<CompositorFrame
> aggregated_frame
=
828 aggregator_
.Aggregate(root_surface_id_
);
830 ASSERT_TRUE(aggregated_frame
);
831 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
833 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
835 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
837 ASSERT_EQ(1u, aggregated_pass_list
.size());
839 const QuadList
& aggregated_quad_list
= aggregated_pass_list
[0]->quad_list
;
841 ASSERT_EQ(7u, aggregated_quad_list
.size());
843 for (auto iter
= aggregated_quad_list
.cbegin();
844 iter
!= aggregated_quad_list
.cend();
846 EXPECT_EQ(blend_modes
[iter
.index()], iter
->shared_quad_state
->blend_mode
)
849 factory_
.Destroy(child_one_surface_id
);
850 factory_
.Destroy(child_two_surface_id
);
851 factory_
.Destroy(grandchild_surface_id
);
854 // This tests that when aggregating a frame with multiple render passes that we
855 // map the transforms for the root pass but do not modify the transform on child
858 // The root surface has one pass with a surface quad transformed by +10 in the y
861 // The middle surface has one pass with a surface quad scaled by 2 in the x
862 // and 3 in the y directions.
864 // The child surface has two passes. The first pass has a quad with a transform
865 // of +5 in the x direction. The second pass has a reference to the first pass'
866 // pass id and a transform of +8 in the x direction.
868 // After aggregation, the child surface's root pass quad should have all
869 // transforms concatenated for a total transform of +23 x, +10 y. The
870 // contributing render pass' transform in the aggregate frame should not be
872 TEST_F(SurfaceAggregatorValidSurfaceTest
, AggregateMultiplePassWithTransform
) {
873 // Innermost child surface.
874 SurfaceId child_surface_id
= allocator_
.GenerateId();
876 factory_
.Create(child_surface_id
);
877 RenderPassId child_pass_id
[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
878 test::Quad child_quads
[][1] = {
879 {test::Quad::SolidColorQuad(SK_ColorGREEN
)},
880 {test::Quad::RenderPassQuad(child_pass_id
[0])},
882 test::Pass child_passes
[] = {
883 test::Pass(child_quads
[0], arraysize(child_quads
[0]), child_pass_id
[0]),
884 test::Pass(child_quads
[1], arraysize(child_quads
[1]),
887 RenderPassList child_pass_list
;
888 AddPasses(&child_pass_list
, gfx::Rect(SurfaceSize()), child_passes
,
889 arraysize(child_passes
));
891 RenderPass
* child_nonroot_pass
= child_pass_list
.at(0u);
892 child_nonroot_pass
->transform_to_root_target
.Translate(8, 0);
893 SharedQuadState
* child_nonroot_pass_sqs
=
894 child_nonroot_pass
->shared_quad_state_list
.front();
895 child_nonroot_pass_sqs
->quad_to_target_transform
.Translate(5, 0);
897 RenderPass
* child_root_pass
= child_pass_list
.at(1u);
898 SharedQuadState
* child_root_pass_sqs
=
899 child_root_pass
->shared_quad_state_list
.front();
900 child_root_pass_sqs
->quad_to_target_transform
.Translate(8, 0);
901 child_root_pass_sqs
->is_clipped
= true;
902 child_root_pass_sqs
->clip_rect
= gfx::Rect(0, 0, 5, 5);
904 scoped_ptr
<DelegatedFrameData
> child_frame_data(new DelegatedFrameData
);
905 child_pass_list
.swap(child_frame_data
->render_pass_list
);
907 scoped_ptr
<CompositorFrame
> child_frame(new CompositorFrame
);
908 child_frame
->delegated_frame_data
= child_frame_data
.Pass();
910 factory_
.SubmitFrame(child_surface_id
, child_frame
.Pass(),
911 SurfaceFactory::DrawCallback());
914 // Middle child surface.
915 SurfaceId middle_surface_id
= allocator_
.GenerateId();
917 factory_
.Create(middle_surface_id
);
918 test::Quad middle_quads
[] = {
919 test::Quad::SurfaceQuad(child_surface_id
, 1.f
)};
920 test::Pass middle_passes
[] = {
921 test::Pass(middle_quads
, arraysize(middle_quads
)),
924 RenderPassList middle_pass_list
;
925 AddPasses(&middle_pass_list
, gfx::Rect(SurfaceSize()), middle_passes
,
926 arraysize(middle_passes
));
928 RenderPass
* middle_root_pass
= middle_pass_list
.at(0u);
929 middle_root_pass
->quad_list
.ElementAt(0)->visible_rect
=
930 gfx::Rect(0, 1, 100, 7);
931 SharedQuadState
* middle_root_pass_sqs
=
932 middle_root_pass
->shared_quad_state_list
.front();
933 middle_root_pass_sqs
->quad_to_target_transform
.Scale(2, 3);
935 scoped_ptr
<DelegatedFrameData
> middle_frame_data(new DelegatedFrameData
);
936 middle_pass_list
.swap(middle_frame_data
->render_pass_list
);
938 scoped_ptr
<CompositorFrame
> middle_frame(new CompositorFrame
);
939 middle_frame
->delegated_frame_data
= middle_frame_data
.Pass();
941 factory_
.SubmitFrame(middle_surface_id
, middle_frame
.Pass(),
942 SurfaceFactory::DrawCallback());
946 test::Quad secondary_quads
[] = {
947 test::Quad::SolidColorQuad(1),
948 test::Quad::SurfaceQuad(middle_surface_id
, 1.f
)};
949 test::Quad root_quads
[] = {test::Quad::SolidColorQuad(1)};
950 test::Pass root_passes
[] = {
951 test::Pass(secondary_quads
, arraysize(secondary_quads
)),
952 test::Pass(root_quads
, arraysize(root_quads
))};
954 RenderPassList root_pass_list
;
955 AddPasses(&root_pass_list
,
956 gfx::Rect(SurfaceSize()),
958 arraysize(root_passes
));
961 ->shared_quad_state_list
.front()
962 ->quad_to_target_transform
.Translate(0, 7);
964 ->shared_quad_state_list
.ElementAt(1)
965 ->quad_to_target_transform
.Translate(0, 10);
966 root_pass_list
.at(0)->quad_list
.ElementAt(1)->visible_rect
=
967 gfx::Rect(0, 0, 8, 100);
969 root_pass_list
[0]->transform_to_root_target
.Translate(10, 5);
971 scoped_ptr
<DelegatedFrameData
> root_frame_data(new DelegatedFrameData
);
972 root_pass_list
.swap(root_frame_data
->render_pass_list
);
974 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
975 root_frame
->delegated_frame_data
= root_frame_data
.Pass();
977 factory_
.SubmitFrame(root_surface_id_
, root_frame
.Pass(),
978 SurfaceFactory::DrawCallback());
980 scoped_ptr
<CompositorFrame
> aggregated_frame
=
981 aggregator_
.Aggregate(root_surface_id_
);
983 ASSERT_TRUE(aggregated_frame
);
984 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
986 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
988 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
990 ASSERT_EQ(3u, aggregated_pass_list
.size());
992 ASSERT_EQ(1u, aggregated_pass_list
[0]->shared_quad_state_list
.size());
994 // The first pass should have one shared quad state for the one solid color
996 EXPECT_EQ(1u, aggregated_pass_list
[0]->shared_quad_state_list
.size());
997 // The second pass should have just two shared quad states. We'll
998 // verify the properties through the quads.
999 EXPECT_EQ(2u, aggregated_pass_list
[1]->shared_quad_state_list
.size());
1001 EXPECT_EQ(1u, aggregated_pass_list
[2]->shared_quad_state_list
.size());
1003 SharedQuadState
* aggregated_first_pass_sqs
=
1004 aggregated_pass_list
[0]->shared_quad_state_list
.front();
1006 // The first pass's transform should be unaffected by the embedding and still
1007 // be a translation by +5 in the x direction.
1008 gfx::Transform expected_aggregated_first_pass_sqs_transform
;
1009 expected_aggregated_first_pass_sqs_transform
.Translate(5, 0);
1010 EXPECT_EQ(expected_aggregated_first_pass_sqs_transform
.ToString(),
1011 aggregated_first_pass_sqs
->quad_to_target_transform
.ToString());
1013 // The first pass's transform to the root target should include the aggregated
1014 // transform, including the transform from the child pass to the root.
1015 gfx::Transform expected_first_pass_transform_to_root_target
;
1016 expected_first_pass_transform_to_root_target
.Translate(10, 5);
1017 expected_first_pass_transform_to_root_target
.Translate(0, 10);
1018 expected_first_pass_transform_to_root_target
.Scale(2, 3);
1019 expected_first_pass_transform_to_root_target
.Translate(8, 0);
1020 EXPECT_EQ(expected_first_pass_transform_to_root_target
.ToString(),
1021 aggregated_pass_list
[0]->transform_to_root_target
.ToString());
1023 ASSERT_EQ(2u, aggregated_pass_list
[1]->quad_list
.size());
1025 gfx::Transform expected_root_pass_quad_transforms
[2];
1026 // The first quad in the root pass is the solid color quad from the original
1027 // root surface. Its transform should be unaffected by the aggregation and
1028 // still be +7 in the y direction.
1029 expected_root_pass_quad_transforms
[0].Translate(0, 7);
1030 // The second quad in the root pass is aggregated from the child surface so
1031 // its transform should be the combination of its original translation
1032 // (0, 10), the middle surface draw quad's scale of (2, 3), and the
1033 // child surface draw quad's translation (8, 0).
1034 expected_root_pass_quad_transforms
[1].Translate(0, 10);
1035 expected_root_pass_quad_transforms
[1].Scale(2, 3);
1036 expected_root_pass_quad_transforms
[1].Translate(8, 0);
1038 for (auto iter
= aggregated_pass_list
[1]->quad_list
.cbegin();
1039 iter
!= aggregated_pass_list
[1]->quad_list
.cend();
1041 EXPECT_EQ(expected_root_pass_quad_transforms
[iter
.index()].ToString(),
1042 iter
->shared_quad_state
->quad_to_target_transform
.ToString())
1047 aggregated_pass_list
[1]->shared_quad_state_list
.ElementAt(1)->is_clipped
);
1049 // The second quad in the root pass is aggregated from the child, so its
1050 // clip rect must be transformed by the child's translation/scale and
1051 // clipped be the visible_rects for both children.
1052 EXPECT_EQ(gfx::Rect(0, 13, 8, 12).ToString(),
1053 aggregated_pass_list
[1]
1054 ->shared_quad_state_list
.ElementAt(1)
1055 ->clip_rect
.ToString());
1057 factory_
.Destroy(middle_surface_id
);
1058 factory_
.Destroy(child_surface_id
);
1061 // Tests that damage rects are aggregated correctly when surfaces change.
1062 TEST_F(SurfaceAggregatorValidSurfaceTest
, AggregateDamageRect
) {
1063 test::Quad child_quads
[] = {test::Quad::RenderPassQuad(RenderPassId(1, 1))};
1064 test::Pass child_passes
[] = {
1065 test::Pass(child_quads
, arraysize(child_quads
), RenderPassId(1, 1))};
1067 RenderPassList child_pass_list
;
1068 AddPasses(&child_pass_list
,
1069 gfx::Rect(SurfaceSize()),
1071 arraysize(child_passes
));
1073 RenderPass
* child_root_pass
= child_pass_list
.at(0u);
1074 SharedQuadState
* child_root_pass_sqs
=
1075 child_root_pass
->shared_quad_state_list
.front();
1076 child_root_pass_sqs
->quad_to_target_transform
.Translate(8, 0);
1078 scoped_ptr
<DelegatedFrameData
> child_frame_data(new DelegatedFrameData
);
1079 child_pass_list
.swap(child_frame_data
->render_pass_list
);
1081 scoped_ptr
<CompositorFrame
> child_frame(new CompositorFrame
);
1082 child_frame
->delegated_frame_data
= child_frame_data
.Pass();
1084 SurfaceId child_surface_id
= allocator_
.GenerateId();
1085 factory_
.Create(child_surface_id
);
1086 factory_
.SubmitFrame(child_surface_id
, child_frame
.Pass(),
1087 SurfaceFactory::DrawCallback());
1089 test::Quad parent_surface_quads
[] = {
1090 test::Quad::SurfaceQuad(child_surface_id
, 1.f
)};
1091 test::Pass parent_surface_passes
[] = {
1092 test::Pass(parent_surface_quads
, arraysize(parent_surface_quads
),
1093 RenderPassId(1, 1))};
1095 RenderPassList parent_surface_pass_list
;
1096 AddPasses(&parent_surface_pass_list
,
1097 gfx::Rect(SurfaceSize()),
1098 parent_surface_passes
,
1099 arraysize(parent_surface_passes
));
1101 // Parent surface is only used to test if the transform is applied correctly
1102 // to the child surface's damage.
1103 scoped_ptr
<DelegatedFrameData
> parent_surface_frame_data(
1104 new DelegatedFrameData
);
1105 parent_surface_pass_list
.swap(parent_surface_frame_data
->render_pass_list
);
1107 scoped_ptr
<CompositorFrame
> parent_surface_frame(new CompositorFrame
);
1108 parent_surface_frame
->delegated_frame_data
= parent_surface_frame_data
.Pass();
1110 SurfaceId parent_surface_id
= allocator_
.GenerateId();
1111 factory_
.Create(parent_surface_id
);
1112 factory_
.SubmitFrame(parent_surface_id
, parent_surface_frame
.Pass(),
1113 SurfaceFactory::DrawCallback());
1115 test::Quad root_surface_quads
[] = {
1116 test::Quad::SurfaceQuad(parent_surface_id
, 1.f
)};
1117 test::Quad root_render_pass_quads
[] = {
1118 test::Quad::RenderPassQuad(RenderPassId(1, 1))};
1120 test::Pass root_passes
[] = {
1121 test::Pass(root_surface_quads
, arraysize(root_surface_quads
),
1122 RenderPassId(1, 1)),
1123 test::Pass(root_render_pass_quads
, arraysize(root_render_pass_quads
),
1124 RenderPassId(2, 1))};
1126 RenderPassList root_pass_list
;
1127 AddPasses(&root_pass_list
,
1128 gfx::Rect(SurfaceSize()),
1130 arraysize(root_passes
));
1132 root_pass_list
.at(0)
1133 ->shared_quad_state_list
.front()
1134 ->quad_to_target_transform
.Translate(0, 10);
1135 root_pass_list
.at(0)->damage_rect
= gfx::Rect(5, 5, 10, 10);
1136 root_pass_list
.at(1)->damage_rect
= gfx::Rect(5, 5, 100, 100);
1138 scoped_ptr
<DelegatedFrameData
> root_frame_data(new DelegatedFrameData
);
1139 root_pass_list
.swap(root_frame_data
->render_pass_list
);
1141 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
1142 root_frame
->delegated_frame_data
= root_frame_data
.Pass();
1144 factory_
.SubmitFrame(root_surface_id_
, root_frame
.Pass(),
1145 SurfaceFactory::DrawCallback());
1147 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1148 aggregator_
.Aggregate(root_surface_id_
);
1150 ASSERT_TRUE(aggregated_frame
);
1151 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1153 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
1155 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1157 ASSERT_EQ(2u, aggregated_pass_list
.size());
1159 // Damage rect for first aggregation should contain entire root surface.
1161 aggregated_pass_list
[1]->damage_rect
.Contains(gfx::Rect(SurfaceSize())));
1164 AddPasses(&child_pass_list
,
1165 gfx::Rect(SurfaceSize()),
1167 arraysize(child_passes
));
1169 RenderPass
* child_root_pass
= child_pass_list
.at(0u);
1170 SharedQuadState
* child_root_pass_sqs
=
1171 child_root_pass
->shared_quad_state_list
.front();
1172 child_root_pass_sqs
->quad_to_target_transform
.Translate(8, 0);
1173 child_root_pass
->damage_rect
= gfx::Rect(10, 10, 10, 10);
1175 scoped_ptr
<DelegatedFrameData
> child_frame_data(new DelegatedFrameData
);
1176 child_pass_list
.swap(child_frame_data
->render_pass_list
);
1178 scoped_ptr
<CompositorFrame
> child_frame(new CompositorFrame
);
1179 child_frame
->delegated_frame_data
= child_frame_data
.Pass();
1181 factory_
.SubmitFrame(child_surface_id
, child_frame
.Pass(),
1182 SurfaceFactory::DrawCallback());
1184 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1185 aggregator_
.Aggregate(root_surface_id_
);
1187 ASSERT_TRUE(aggregated_frame
);
1188 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1190 DelegatedFrameData
* frame_data
=
1191 aggregated_frame
->delegated_frame_data
.get();
1193 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1195 ASSERT_EQ(2u, aggregated_pass_list
.size());
1197 // Outer surface didn't change, so transformed inner damage rect should be
1199 EXPECT_EQ(gfx::Rect(10, 20, 10, 10).ToString(),
1200 aggregated_pass_list
[1]->damage_rect
.ToString());
1204 RenderPassList root_pass_list
;
1205 AddPasses(&root_pass_list
,
1206 gfx::Rect(SurfaceSize()),
1208 arraysize(root_passes
));
1210 root_pass_list
.at(0)
1211 ->shared_quad_state_list
.front()
1212 ->quad_to_target_transform
.Translate(0, 10);
1213 root_pass_list
.at(0)->damage_rect
= gfx::Rect(0, 0, 1, 1);
1215 scoped_ptr
<DelegatedFrameData
> root_frame_data(new DelegatedFrameData
);
1216 root_pass_list
.swap(root_frame_data
->render_pass_list
);
1218 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
1219 root_frame
->delegated_frame_data
= root_frame_data
.Pass();
1221 factory_
.SubmitFrame(root_surface_id_
, root_frame
.Pass(),
1222 SurfaceFactory::DrawCallback());
1226 RenderPassList root_pass_list
;
1227 AddPasses(&root_pass_list
,
1228 gfx::Rect(SurfaceSize()),
1230 arraysize(root_passes
));
1232 root_pass_list
.at(0)
1233 ->shared_quad_state_list
.front()
1234 ->quad_to_target_transform
.Translate(0, 10);
1235 root_pass_list
.at(0)->damage_rect
= gfx::Rect(1, 1, 1, 1);
1237 scoped_ptr
<DelegatedFrameData
> root_frame_data(new DelegatedFrameData
);
1238 root_pass_list
.swap(root_frame_data
->render_pass_list
);
1240 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
1241 root_frame
->delegated_frame_data
= root_frame_data
.Pass();
1243 factory_
.SubmitFrame(root_surface_id_
, root_frame
.Pass(),
1244 SurfaceFactory::DrawCallback());
1246 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1247 aggregator_
.Aggregate(root_surface_id_
);
1249 ASSERT_TRUE(aggregated_frame
);
1250 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1252 DelegatedFrameData
* frame_data
=
1253 aggregated_frame
->delegated_frame_data
.get();
1255 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1257 ASSERT_EQ(2u, aggregated_pass_list
.size());
1259 // The root surface was enqueued without being aggregated once, so it should
1260 // be treated as completely damaged.
1261 EXPECT_TRUE(aggregated_pass_list
[1]->damage_rect
.Contains(
1262 gfx::Rect(SurfaceSize())));
1265 // No Surface changed, so no damage should be given.
1267 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1268 aggregator_
.Aggregate(root_surface_id_
);
1270 ASSERT_TRUE(aggregated_frame
);
1271 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1273 DelegatedFrameData
* frame_data
=
1274 aggregated_frame
->delegated_frame_data
.get();
1276 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1278 ASSERT_EQ(2u, aggregated_pass_list
.size());
1280 EXPECT_TRUE(aggregated_pass_list
[1]->damage_rect
.IsEmpty());
1283 // SetFullDamageRectForSurface should cause the entire output to be
1284 // marked as damaged.
1286 aggregator_
.SetFullDamageForSurface(root_surface_id_
);
1287 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1288 aggregator_
.Aggregate(root_surface_id_
);
1290 ASSERT_TRUE(aggregated_frame
);
1291 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1293 DelegatedFrameData
* frame_data
=
1294 aggregated_frame
->delegated_frame_data
.get();
1296 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1298 ASSERT_EQ(2u, aggregated_pass_list
.size());
1300 EXPECT_TRUE(aggregated_pass_list
[1]->damage_rect
.Contains(
1301 gfx::Rect(SurfaceSize())));
1304 factory_
.Destroy(child_surface_id
);
1307 class SurfaceAggregatorPartialSwapTest
1308 : public SurfaceAggregatorValidSurfaceTest
{
1310 SurfaceAggregatorPartialSwapTest()
1311 : SurfaceAggregatorValidSurfaceTest(true) {}
1314 // Tests that quads outside the damage rect are ignored.
1315 TEST_F(SurfaceAggregatorPartialSwapTest
, IgnoreOutside
) {
1316 SurfaceId child_surface_id
= allocator_
.GenerateId();
1317 factory_
.Create(child_surface_id
);
1318 // The child surface has two quads, one with a visible rect of 13,13 4x4 and
1319 // the other other with a visible rect of 10,10 2x2 (relative to root target
1322 RenderPassId child_pass_id
= RenderPassId(1, 1);
1323 test::Quad child_quads1
[] = {test::Quad::RenderPassQuad(child_pass_id
)};
1324 test::Quad child_quads2
[] = {test::Quad::RenderPassQuad(child_pass_id
)};
1325 test::Pass child_passes
[] = {
1326 test::Pass(child_quads1
, arraysize(child_quads1
), child_pass_id
),
1327 test::Pass(child_quads2
, arraysize(child_quads2
), child_pass_id
)};
1329 RenderPassList child_pass_list
;
1330 AddPasses(&child_pass_list
, gfx::Rect(SurfaceSize()), child_passes
,
1331 arraysize(child_passes
));
1333 child_pass_list
.at(0u)->quad_list
.ElementAt(0)->visible_rect
=
1334 gfx::Rect(1, 1, 2, 2);
1335 SharedQuadState
* child_sqs
=
1336 child_pass_list
.at(0u)->shared_quad_state_list
.ElementAt(0u);
1337 child_sqs
->quad_to_target_transform
.Translate(1, 1);
1338 child_sqs
->quad_to_target_transform
.Scale(2, 2);
1340 child_pass_list
.at(1u)->quad_list
.ElementAt(0)->visible_rect
=
1341 gfx::Rect(0, 0, 2, 2);
1343 SubmitPassListAsFrame(child_surface_id
, &child_pass_list
);
1347 test::Quad root_quads
[] = {test::Quad::SurfaceQuad(child_surface_id
, 1.f
)};
1349 test::Pass root_passes
[] = {test::Pass(root_quads
, arraysize(root_quads
))};
1351 RenderPassList root_pass_list
;
1352 AddPasses(&root_pass_list
, gfx::Rect(SurfaceSize()), root_passes
,
1353 arraysize(root_passes
));
1355 RenderPass
* root_pass
= root_pass_list
.at(0u);
1356 root_pass
->shared_quad_state_list
.front()
1357 ->quad_to_target_transform
.Translate(10, 10);
1358 root_pass
->damage_rect
= gfx::Rect(0, 0, 1, 1);
1360 SubmitPassListAsFrame(root_surface_id_
, &root_pass_list
);
1363 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1364 aggregator_
.Aggregate(root_surface_id_
);
1366 ASSERT_TRUE(aggregated_frame
);
1367 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1369 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
1371 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1373 ASSERT_EQ(2u, aggregated_pass_list
.size());
1375 // Damage rect for first aggregation should contain entire root surface.
1376 EXPECT_EQ(gfx::Rect(0, 0, 15, 15), aggregated_pass_list
[1]->damage_rect
);
1377 EXPECT_EQ(1u, aggregated_pass_list
[0]->quad_list
.size());
1378 EXPECT_EQ(1u, aggregated_pass_list
[1]->quad_list
.size());
1380 // Create a root surface with a smaller damage rect.
1382 test::Quad root_quads
[] = {test::Quad::SurfaceQuad(child_surface_id
, 1.f
)};
1384 test::Pass root_passes
[] = {test::Pass(root_quads
, arraysize(root_quads
))};
1386 RenderPassList root_pass_list
;
1387 AddPasses(&root_pass_list
, gfx::Rect(SurfaceSize()), root_passes
,
1388 arraysize(root_passes
));
1390 RenderPass
* root_pass
= root_pass_list
.at(0u);
1391 root_pass
->shared_quad_state_list
.front()
1392 ->quad_to_target_transform
.Translate(10, 10);
1393 root_pass
->damage_rect
= gfx::Rect(10, 10, 2, 2);
1394 SubmitPassListAsFrame(root_surface_id_
, &root_pass_list
);
1398 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1399 aggregator_
.Aggregate(root_surface_id_
);
1401 ASSERT_TRUE(aggregated_frame
);
1402 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1404 DelegatedFrameData
* frame_data
=
1405 aggregated_frame
->delegated_frame_data
.get();
1407 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1409 ASSERT_EQ(2u, aggregated_pass_list
.size());
1411 // Only first quad from surface is inside damage rect and should be
1413 EXPECT_EQ(gfx::Rect(10, 10, 2, 2), aggregated_pass_list
[1]->damage_rect
);
1414 EXPECT_EQ(0u, aggregated_pass_list
[0]->quad_list
.size());
1415 EXPECT_EQ(1u, aggregated_pass_list
[1]->quad_list
.size());
1416 EXPECT_EQ(gfx::Rect(0, 0, 2, 2),
1417 aggregated_pass_list
[1]->quad_list
.back()->visible_rect
);
1420 // New child frame has same content and no damage, but has a
1421 // CopyOutputRequest.
1423 RenderPassId child_pass_id
= RenderPassId(1, 1);
1424 test::Quad child_quads1
[] = {test::Quad::RenderPassQuad(child_pass_id
)};
1425 test::Quad child_quads2
[] = {test::Quad::RenderPassQuad(child_pass_id
)};
1426 test::Pass child_passes
[] = {
1427 test::Pass(child_quads1
, arraysize(child_quads1
), child_pass_id
),
1428 test::Pass(child_quads2
, arraysize(child_quads2
), child_pass_id
)};
1430 RenderPassList child_pass_list
;
1431 AddPasses(&child_pass_list
, gfx::Rect(SurfaceSize()), child_passes
,
1432 arraysize(child_passes
));
1434 child_pass_list
.at(0u)->quad_list
.ElementAt(0)->visible_rect
=
1435 gfx::Rect(1, 1, 2, 2);
1436 SharedQuadState
* child_sqs
=
1437 child_pass_list
.at(0u)->shared_quad_state_list
.ElementAt(0u);
1438 child_sqs
->quad_to_target_transform
.Translate(1, 1);
1439 child_sqs
->quad_to_target_transform
.Scale(2, 2);
1441 child_pass_list
.at(1u)->quad_list
.ElementAt(0)->visible_rect
=
1442 gfx::Rect(0, 0, 2, 2);
1444 RenderPass
* child_root_pass
= child_pass_list
.at(1u);
1446 child_root_pass
->copy_requests
.push_back(
1447 CopyOutputRequest::CreateEmptyRequest());
1448 child_root_pass
->damage_rect
= gfx::Rect();
1449 SubmitPassListAsFrame(child_surface_id
, &child_pass_list
);
1453 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1454 aggregator_
.Aggregate(root_surface_id_
);
1456 ASSERT_TRUE(aggregated_frame
);
1457 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1459 DelegatedFrameData
* frame_data
=
1460 aggregated_frame
->delegated_frame_data
.get();
1462 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1464 // Output frame should have no damage, but all quads included.
1465 ASSERT_EQ(3u, aggregated_pass_list
.size());
1467 EXPECT_TRUE(aggregated_pass_list
[1]->damage_rect
.IsEmpty());
1468 ASSERT_EQ(1u, aggregated_pass_list
[0]->quad_list
.size());
1469 ASSERT_EQ(1u, aggregated_pass_list
[1]->quad_list
.size());
1470 EXPECT_EQ(gfx::Rect(1, 1, 2, 2),
1471 aggregated_pass_list
[0]->quad_list
.ElementAt(0)->visible_rect
);
1472 EXPECT_EQ(gfx::Rect(0, 0, 2, 2),
1473 aggregated_pass_list
[1]->quad_list
.ElementAt(0)->visible_rect
);
1477 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1478 aggregator_
.Aggregate(root_surface_id_
);
1480 ASSERT_TRUE(aggregated_frame
);
1481 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1483 DelegatedFrameData
* frame_data
=
1484 aggregated_frame
->delegated_frame_data
.get();
1486 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1487 // There were no changes since last aggregation, so output should be empty
1488 // and have no damage.
1489 ASSERT_EQ(1u, aggregated_pass_list
.size());
1490 EXPECT_TRUE(aggregated_pass_list
[0]->damage_rect
.IsEmpty());
1491 ASSERT_EQ(0u, aggregated_pass_list
[0]->quad_list
.size());
1494 factory_
.Destroy(child_surface_id
);
1497 class SurfaceAggregatorWithResourcesTest
: public testing::Test
{
1499 void SetUp() override
{
1500 output_surface_
= FakeOutputSurface::CreateSoftware(
1501 make_scoped_ptr(new SoftwareOutputDevice
));
1502 output_surface_
->BindToClient(&output_surface_client_
);
1503 shared_bitmap_manager_
.reset(new TestSharedBitmapManager
);
1505 resource_provider_
= FakeResourceProvider::Create(
1506 output_surface_
.get(), shared_bitmap_manager_
.get());
1509 new SurfaceAggregator(&manager_
, resource_provider_
.get(), false));
1513 SurfaceManager manager_
;
1514 FakeOutputSurfaceClient output_surface_client_
;
1515 scoped_ptr
<OutputSurface
> output_surface_
;
1516 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
1517 scoped_ptr
<ResourceProvider
> resource_provider_
;
1518 scoped_ptr
<SurfaceAggregator
> aggregator_
;
1521 class ResourceTrackingSurfaceFactoryClient
: public SurfaceFactoryClient
{
1523 ResourceTrackingSurfaceFactoryClient() {}
1524 ~ResourceTrackingSurfaceFactoryClient() override
{}
1526 void ReturnResources(const ReturnedResourceArray
& resources
) override
{
1527 returned_resources_
= resources
;
1530 ReturnedResourceArray
returned_resources() const {
1531 return returned_resources_
;
1535 ReturnedResourceArray returned_resources_
;
1537 DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient
);
1540 void SubmitFrameWithResources(ResourceId
* resource_ids
,
1541 size_t num_resource_ids
,
1544 SurfaceFactory
* factory
,
1545 SurfaceId surface_id
) {
1546 scoped_ptr
<DelegatedFrameData
> frame_data(new DelegatedFrameData
);
1547 scoped_ptr
<RenderPass
> pass
= RenderPass::Create();
1548 pass
->id
= RenderPassId(1, 1);
1549 SharedQuadState
* sqs
= pass
->CreateAndAppendSharedQuadState();
1551 if (!child_id
.is_null()) {
1552 SurfaceDrawQuad
* surface_quad
=
1553 pass
->CreateAndAppendDrawQuad
<SurfaceDrawQuad
>();
1554 surface_quad
->SetNew(sqs
, gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1),
1558 for (size_t i
= 0u; i
< num_resource_ids
; ++i
) {
1559 TransferableResource resource
;
1560 resource
.id
= resource_ids
[i
];
1561 // ResourceProvider is software, so only software resources are valid.
1562 resource
.is_software
= valid
;
1563 frame_data
->resource_list
.push_back(resource
);
1564 TextureDrawQuad
* quad
= pass
->CreateAndAppendDrawQuad
<TextureDrawQuad
>();
1565 const gfx::Rect rect
;
1566 const gfx::Rect opaque_rect
;
1567 const gfx::Rect visible_rect
;
1568 bool needs_blending
= false;
1569 bool premultiplied_alpha
= false;
1570 const gfx::PointF uv_top_left
;
1571 const gfx::PointF uv_bottom_right
;
1572 SkColor background_color
= SK_ColorGREEN
;
1573 const float vertex_opacity
[4] = {0.f
, 0.f
, 1.f
, 1.f
};
1574 bool flipped
= false;
1575 bool nearest_neighbor
= false;
1576 quad
->SetAll(sqs
, rect
, opaque_rect
, visible_rect
, needs_blending
,
1577 resource_ids
[i
], gfx::Size(), false, premultiplied_alpha
,
1578 uv_top_left
, uv_bottom_right
, background_color
, vertex_opacity
,
1579 flipped
, nearest_neighbor
);
1581 frame_data
->render_pass_list
.push_back(pass
.Pass());
1582 scoped_ptr
<CompositorFrame
> frame(new CompositorFrame
);
1583 frame
->delegated_frame_data
= frame_data
.Pass();
1584 factory
->SubmitFrame(surface_id
, frame
.Pass(),
1585 SurfaceFactory::DrawCallback());
1588 TEST_F(SurfaceAggregatorWithResourcesTest
, TakeResourcesOneSurface
) {
1589 ResourceTrackingSurfaceFactoryClient client
;
1590 SurfaceFactory
factory(&manager_
, &client
);
1591 SurfaceId
surface_id(7u);
1592 factory
.Create(surface_id
);
1594 ResourceId ids
[] = {11, 12, 13};
1595 SubmitFrameWithResources(ids
, arraysize(ids
), true, SurfaceId(), &factory
,
1598 scoped_ptr
<CompositorFrame
> frame
= aggregator_
->Aggregate(surface_id
);
1600 // Nothing should be available to be returned yet.
1601 EXPECT_TRUE(client
.returned_resources().empty());
1603 SubmitFrameWithResources(NULL
, 0u, true, SurfaceId(), &factory
, surface_id
);
1605 frame
= aggregator_
->Aggregate(surface_id
);
1607 ASSERT_EQ(3u, client
.returned_resources().size());
1608 ResourceId returned_ids
[3];
1609 for (size_t i
= 0; i
< 3; ++i
) {
1610 returned_ids
[i
] = client
.returned_resources()[i
].id
;
1612 EXPECT_THAT(returned_ids
,
1613 testing::WhenSorted(testing::ElementsAreArray(ids
)));
1614 factory
.Destroy(surface_id
);
1617 TEST_F(SurfaceAggregatorWithResourcesTest
, TakeInvalidResources
) {
1618 ResourceTrackingSurfaceFactoryClient client
;
1619 SurfaceFactory
factory(&manager_
, &client
);
1620 SurfaceId
surface_id(7u);
1621 factory
.Create(surface_id
);
1623 scoped_ptr
<DelegatedFrameData
> frame_data(new DelegatedFrameData
);
1624 scoped_ptr
<RenderPass
> pass
= RenderPass::Create();
1625 pass
->id
= RenderPassId(1, 1);
1626 TransferableResource resource
;
1628 // ResourceProvider is software but resource is not, so it should be
1630 resource
.is_software
= false;
1631 frame_data
->resource_list
.push_back(resource
);
1632 frame_data
->render_pass_list
.push_back(pass
.Pass());
1633 scoped_ptr
<CompositorFrame
> frame(new CompositorFrame
);
1634 frame
->delegated_frame_data
= frame_data
.Pass();
1635 factory
.SubmitFrame(surface_id
, frame
.Pass(), SurfaceFactory::DrawCallback());
1637 scoped_ptr
<CompositorFrame
> returned_frame
=
1638 aggregator_
->Aggregate(surface_id
);
1640 // Nothing should be available to be returned yet.
1641 EXPECT_TRUE(client
.returned_resources().empty());
1643 SubmitFrameWithResources(NULL
, 0, true, SurfaceId(), &factory
, surface_id
);
1644 ASSERT_EQ(1u, client
.returned_resources().size());
1645 EXPECT_EQ(11u, client
.returned_resources()[0].id
);
1647 factory
.Destroy(surface_id
);
1650 TEST_F(SurfaceAggregatorWithResourcesTest
, TwoSurfaces
) {
1651 ResourceTrackingSurfaceFactoryClient client
;
1652 SurfaceFactory
factory(&manager_
, &client
);
1653 SurfaceId
surface_id(7u);
1654 factory
.Create(surface_id
);
1655 SurfaceId
surface_id2(8u);
1656 factory
.Create(surface_id2
);
1658 ResourceId ids
[] = {11, 12, 13};
1659 SubmitFrameWithResources(ids
, arraysize(ids
), true, SurfaceId(), &factory
,
1661 ResourceId ids2
[] = {14, 15, 16};
1662 SubmitFrameWithResources(ids2
, arraysize(ids2
), true, SurfaceId(), &factory
,
1665 scoped_ptr
<CompositorFrame
> frame
= aggregator_
->Aggregate(surface_id
);
1667 SubmitFrameWithResources(NULL
, 0, true, SurfaceId(), &factory
, surface_id
);
1669 // Nothing should be available to be returned yet.
1670 EXPECT_TRUE(client
.returned_resources().empty());
1672 frame
= aggregator_
->Aggregate(surface_id2
);
1674 // surface_id wasn't referenced, so its resources should be returned.
1675 ASSERT_EQ(3u, client
.returned_resources().size());
1676 ResourceId returned_ids
[3];
1677 for (size_t i
= 0; i
< 3; ++i
) {
1678 returned_ids
[i
] = client
.returned_resources()[i
].id
;
1680 EXPECT_THAT(returned_ids
,
1681 testing::WhenSorted(testing::ElementsAreArray(ids
)));
1682 EXPECT_EQ(3u, resource_provider_
->num_resources());
1683 factory
.Destroy(surface_id
);
1684 factory
.Destroy(surface_id2
);
1687 // Ensure that aggregator completely ignores Surfaces that reference invalid
1689 TEST_F(SurfaceAggregatorWithResourcesTest
, InvalidChildSurface
) {
1690 ResourceTrackingSurfaceFactoryClient client
;
1691 SurfaceFactory
factory(&manager_
, &client
);
1692 SurfaceId
root_surface_id(7u);
1693 factory
.Create(root_surface_id
);
1694 SurfaceId
middle_surface_id(8u);
1695 factory
.Create(middle_surface_id
);
1696 SurfaceId
child_surface_id(9u);
1697 factory
.Create(child_surface_id
);
1699 ResourceId ids
[] = {14, 15, 16};
1700 SubmitFrameWithResources(ids
, arraysize(ids
), true, SurfaceId(), &factory
,
1703 ResourceId ids2
[] = {17, 18, 19};
1704 SubmitFrameWithResources(ids2
, arraysize(ids2
), false, child_surface_id
,
1705 &factory
, middle_surface_id
);
1707 ResourceId ids3
[] = {20, 21, 22};
1708 SubmitFrameWithResources(ids3
, arraysize(ids3
), true, middle_surface_id
,
1709 &factory
, root_surface_id
);
1711 scoped_ptr
<CompositorFrame
> frame
;
1712 frame
= aggregator_
->Aggregate(root_surface_id
);
1714 RenderPassList
* pass_list
= &frame
->delegated_frame_data
->render_pass_list
;
1715 ASSERT_EQ(1u, pass_list
->size());
1716 EXPECT_EQ(1u, pass_list
->back()->shared_quad_state_list
.size());
1717 EXPECT_EQ(3u, pass_list
->back()->quad_list
.size());
1719 SubmitFrameWithResources(ids2
, arraysize(ids
), true, child_surface_id
,
1720 &factory
, middle_surface_id
);
1722 frame
= aggregator_
->Aggregate(root_surface_id
);
1724 pass_list
= &frame
->delegated_frame_data
->render_pass_list
;
1725 ASSERT_EQ(1u, pass_list
->size());
1726 EXPECT_EQ(3u, pass_list
->back()->shared_quad_state_list
.size());
1727 EXPECT_EQ(9u, pass_list
->back()->quad_list
.size());
1729 factory
.Destroy(root_surface_id
);
1730 factory
.Destroy(child_surface_id
);
1731 factory
.Destroy(middle_surface_id
);