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"
32 SurfaceId
InvalidSurfaceId() {
33 static SurfaceId invalid
;
34 invalid
.id
= static_cast<uint64_t>(-1);
38 gfx::Size
SurfaceSize() {
39 static gfx::Size
size(5, 5);
43 class EmptySurfaceFactoryClient
: public SurfaceFactoryClient
{
45 void ReturnResources(const ReturnedResourceArray
& resources
) override
{}
48 class SurfaceAggregatorTest
: public testing::Test
{
50 SurfaceAggregatorTest()
51 : factory_(&manager_
, &empty_client_
), aggregator_(&manager_
, NULL
) {}
54 SurfaceManager manager_
;
55 EmptySurfaceFactoryClient empty_client_
;
56 SurfaceFactory factory_
;
57 SurfaceAggregator aggregator_
;
60 TEST_F(SurfaceAggregatorTest
, ValidSurfaceNoFrame
) {
62 factory_
.Create(one_id
);
63 scoped_ptr
<CompositorFrame
> frame
= aggregator_
.Aggregate(one_id
);
65 factory_
.Destroy(one_id
);
68 class SurfaceAggregatorValidSurfaceTest
: public SurfaceAggregatorTest
{
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
++) {
109 aggregator_
.previous_contained_surfaces().find(surface_ids
[i
]) !=
110 aggregator_
.previous_contained_surfaces().end());
114 void SubmitFrame(test::Pass
* passes
,
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());
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
};
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
++) {
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()),
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
++) {
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),
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
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
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
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
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()};
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
};
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_
};
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
};
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
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
);
680 RenderPassDrawQuad::MaterialCast(render_pass_quads
[0])->render_pass_id
);
682 ASSERT_EQ(render_pass_quads
[1]->material
, DrawQuad::RENDER_PASS
);
685 RenderPassDrawQuad::MaterialCast(render_pass_quads
[1])->render_pass_id
);
686 factory_
.Destroy(child_surface_id
);
689 void AddSolidColorQuadWithBlendMode(const gfx::Size
& size
,
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;
700 bool force_anti_aliasing_off
= false;
701 SharedQuadState
* sqs
= pass
->CreateAndAppendSharedQuadState();
702 sqs
->SetAll(content_to_target_transform
,
704 visible_content_rect
,
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
,
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();
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();
842 EXPECT_EQ(blend_modes
[iter
.index()], iter
->shared_quad_state
->blend_mode
)
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
854 // The root surface has one pass with a surface quad transformed by +10 in the y
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
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]),
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());
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()),
954 arraysize(root_passes
));
957 ->shared_quad_state_list
.front()
958 ->content_to_target_transform
.Translate(0, 7);
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
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();
1037 EXPECT_EQ(expected_root_pass_quad_transforms
[iter
.index()].ToString(),
1038 iter
->quadTransform().ToString())
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()),
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()),
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.
1129 aggregated_pass_list
[1]->damage_rect
.Contains(gfx::Rect(SurfaceSize())));
1132 AddPasses(&child_pass_list
,
1133 gfx::Rect(SurfaceSize()),
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
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()),
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()),
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
{
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(),
1253 new SurfaceAggregator(&manager_
, resource_provider_
.get()));
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
{
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_
;
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;
1315 premultiplied_alpha
,
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
;
1371 // ResourceProvider is software but resource is not, so it should be
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
);