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