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
, MultiPassSimpleFrame
) {
159 test::Quad quads
[][2] = {{test::Quad::SolidColorQuad(SK_ColorWHITE
),
160 test::Quad::SolidColorQuad(SK_ColorLTGRAY
)},
161 {test::Quad::SolidColorQuad(SK_ColorGRAY
),
162 test::Quad::SolidColorQuad(SK_ColorDKGRAY
)}};
163 test::Pass passes
[] = {
164 test::Pass(quads
[0], arraysize(quads
[0]), RenderPassId(1, 1)),
165 test::Pass(quads
[1], arraysize(quads
[1]), RenderPassId(1, 2))};
167 SubmitFrame(passes
, arraysize(passes
), root_surface_id_
);
169 SurfaceId ids
[] = {root_surface_id_
};
170 AggregateAndVerify(passes
, arraysize(passes
), ids
, arraysize(ids
));
173 // This tests very simple embedding. root_surface has a frame containing a few
174 // solid color quads and a surface quad referencing embedded_surface.
175 // embedded_surface has a frame containing only a solid color quad. The solid
176 // color quad should be aggregated into the final frame.
177 TEST_F(SurfaceAggregatorValidSurfaceTest
, SimpleSurfaceReference
) {
178 SurfaceId embedded_surface_id
= allocator_
.GenerateId();
179 factory_
.Create(embedded_surface_id
, SurfaceSize());
181 test::Quad embedded_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
)};
182 test::Pass embedded_passes
[] = {
183 test::Pass(embedded_quads
, arraysize(embedded_quads
))};
185 SubmitFrame(embedded_passes
, arraysize(embedded_passes
), embedded_surface_id
);
187 test::Quad root_quads
[] = {test::Quad::SolidColorQuad(SK_ColorWHITE
),
188 test::Quad::SurfaceQuad(embedded_surface_id
),
189 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
190 test::Pass root_passes
[] = {test::Pass(root_quads
, arraysize(root_quads
))};
192 SubmitFrame(root_passes
, arraysize(root_passes
), root_surface_id_
);
194 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorWHITE
),
195 test::Quad::SolidColorQuad(SK_ColorGREEN
),
196 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
197 test::Pass expected_passes
[] = {
198 test::Pass(expected_quads
, arraysize(expected_quads
))};
199 SurfaceId ids
[] = {root_surface_id_
, embedded_surface_id
};
201 expected_passes
, arraysize(expected_passes
), ids
, arraysize(ids
));
203 factory_
.Destroy(embedded_surface_id
);
206 TEST_F(SurfaceAggregatorValidSurfaceTest
, CopyRequest
) {
207 SurfaceId embedded_surface_id
= allocator_
.GenerateId();
208 factory_
.Create(embedded_surface_id
, SurfaceSize());
210 test::Quad embedded_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
)};
211 test::Pass embedded_passes
[] = {
212 test::Pass(embedded_quads
, arraysize(embedded_quads
))};
214 SubmitFrame(embedded_passes
, arraysize(embedded_passes
), embedded_surface_id
);
215 scoped_ptr
<CopyOutputRequest
> copy_request(
216 CopyOutputRequest::CreateEmptyRequest());
217 CopyOutputRequest
* copy_request_ptr
= copy_request
.get();
218 factory_
.RequestCopyOfSurface(embedded_surface_id
, copy_request
.Pass());
220 test::Quad root_quads
[] = {test::Quad::SolidColorQuad(SK_ColorWHITE
),
221 test::Quad::SurfaceQuad(embedded_surface_id
),
222 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
223 test::Pass root_passes
[] = {test::Pass(root_quads
, arraysize(root_quads
))};
225 SubmitFrame(root_passes
, arraysize(root_passes
), root_surface_id_
);
227 scoped_ptr
<CompositorFrame
> aggregated_frame
=
228 aggregator_
.Aggregate(root_surface_id_
);
230 ASSERT_TRUE(aggregated_frame
);
231 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
233 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
235 test::Quad expected_quads
[] = {
236 test::Quad::SolidColorQuad(SK_ColorWHITE
),
237 test::Quad::RenderPassQuad(frame_data
->render_pass_list
[0]->id
),
238 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
239 test::Pass expected_passes
[] = {
240 test::Pass(embedded_quads
, arraysize(embedded_quads
)),
241 test::Pass(expected_quads
, arraysize(expected_quads
))};
242 TestPassesMatchExpectations(expected_passes
,
243 arraysize(expected_passes
),
244 &frame_data
->render_pass_list
);
245 ASSERT_EQ(2u, frame_data
->render_pass_list
.size());
246 ASSERT_EQ(1u, frame_data
->render_pass_list
[0]->copy_requests
.size());
247 DCHECK_EQ(copy_request_ptr
,
248 frame_data
->render_pass_list
[0]->copy_requests
[0]);
250 SurfaceId surface_ids
[] = {root_surface_id_
, embedded_surface_id
};
251 EXPECT_EQ(arraysize(surface_ids
),
252 aggregator_
.previous_contained_surfaces().size());
253 for (size_t i
= 0; i
< arraysize(surface_ids
); i
++) {
255 aggregator_
.previous_contained_surfaces().find(surface_ids
[i
]) !=
256 aggregator_
.previous_contained_surfaces().end());
259 factory_
.Destroy(embedded_surface_id
);
262 // Root surface may contain copy requests.
263 TEST_F(SurfaceAggregatorValidSurfaceTest
, RootCopyRequest
) {
264 SurfaceId embedded_surface_id
= allocator_
.GenerateId();
265 factory_
.Create(embedded_surface_id
, SurfaceSize());
267 test::Quad embedded_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
)};
268 test::Pass embedded_passes
[] = {
269 test::Pass(embedded_quads
, arraysize(embedded_quads
))};
271 SubmitFrame(embedded_passes
, arraysize(embedded_passes
), embedded_surface_id
);
272 scoped_ptr
<CopyOutputRequest
> copy_request(
273 CopyOutputRequest::CreateEmptyRequest());
274 CopyOutputRequest
* copy_request_ptr
= copy_request
.get();
275 scoped_ptr
<CopyOutputRequest
> copy_request2(
276 CopyOutputRequest::CreateEmptyRequest());
277 CopyOutputRequest
* copy_request2_ptr
= copy_request2
.get();
279 test::Quad root_quads
[] = {test::Quad::SolidColorQuad(SK_ColorWHITE
),
280 test::Quad::SurfaceQuad(embedded_surface_id
),
281 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
282 test::Quad root_quads2
[] = {test::Quad::SolidColorQuad(SK_ColorRED
)};
283 test::Pass root_passes
[] = {
284 test::Pass(root_quads
, arraysize(root_quads
), RenderPassId(1, 1)),
285 test::Pass(root_quads2
, arraysize(root_quads2
), RenderPassId(1, 2))};
287 RenderPassList pass_list
;
288 AddPasses(&pass_list
,
289 gfx::Rect(SurfaceSize()),
291 arraysize(root_passes
));
292 pass_list
[0]->copy_requests
.push_back(copy_request
.Pass());
293 pass_list
[1]->copy_requests
.push_back(copy_request2
.Pass());
295 scoped_ptr
<DelegatedFrameData
> frame_data(new DelegatedFrameData
);
296 pass_list
.swap(frame_data
->render_pass_list
);
298 scoped_ptr
<CompositorFrame
> frame(new CompositorFrame
);
299 frame
->delegated_frame_data
= frame_data
.Pass();
301 factory_
.SubmitFrame(root_surface_id_
, frame
.Pass(), base::Closure());
304 scoped_ptr
<CompositorFrame
> aggregated_frame
=
305 aggregator_
.Aggregate(root_surface_id_
);
307 ASSERT_TRUE(aggregated_frame
);
308 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
310 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
312 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorWHITE
),
313 test::Quad::SolidColorQuad(SK_ColorGREEN
),
314 test::Quad::SolidColorQuad(SK_ColorBLACK
)};
315 test::Pass expected_passes
[] = {
316 test::Pass(expected_quads
, arraysize(expected_quads
)),
317 test::Pass(root_quads2
, arraysize(root_quads2
))};
318 TestPassesMatchExpectations(expected_passes
,
319 arraysize(expected_passes
),
320 &frame_data
->render_pass_list
);
321 ASSERT_EQ(2u, frame_data
->render_pass_list
.size());
322 ASSERT_EQ(1u, frame_data
->render_pass_list
[0]->copy_requests
.size());
323 DCHECK_EQ(copy_request_ptr
,
324 frame_data
->render_pass_list
[0]->copy_requests
[0]);
325 ASSERT_EQ(1u, frame_data
->render_pass_list
[1]->copy_requests
.size());
326 DCHECK_EQ(copy_request2_ptr
,
327 frame_data
->render_pass_list
[1]->copy_requests
[0]);
329 SurfaceId surface_ids
[] = {root_surface_id_
, embedded_surface_id
};
330 EXPECT_EQ(arraysize(surface_ids
),
331 aggregator_
.previous_contained_surfaces().size());
332 for (size_t i
= 0; i
< arraysize(surface_ids
); i
++) {
334 aggregator_
.previous_contained_surfaces().find(surface_ids
[i
]) !=
335 aggregator_
.previous_contained_surfaces().end());
338 // Ensure copy requests have been removed from root surface.
339 const CompositorFrame
* original_frame
=
340 manager_
.GetSurfaceForId(root_surface_id_
)->GetEligibleFrame();
341 RenderPassList
& original_pass_list
=
342 original_frame
->delegated_frame_data
->render_pass_list
;
343 ASSERT_EQ(2u, original_pass_list
.size());
344 DCHECK(original_pass_list
[0]->copy_requests
.empty());
345 DCHECK(original_pass_list
[1]->copy_requests
.empty());
347 factory_
.Destroy(embedded_surface_id
);
350 // This tests referencing a surface that has multiple render passes.
351 TEST_F(SurfaceAggregatorValidSurfaceTest
, MultiPassSurfaceReference
) {
352 SurfaceId embedded_surface_id
= child_allocator_
.GenerateId();
353 factory_
.Create(embedded_surface_id
, SurfaceSize());
355 RenderPassId pass_ids
[] = {RenderPassId(1, 1), RenderPassId(1, 2),
358 test::Quad embedded_quads
[][2] = {
359 {test::Quad::SolidColorQuad(1), test::Quad::SolidColorQuad(2)},
360 {test::Quad::SolidColorQuad(3), test::Quad::RenderPassQuad(pass_ids
[0])},
361 {test::Quad::SolidColorQuad(4), test::Quad::RenderPassQuad(pass_ids
[1])}};
362 test::Pass embedded_passes
[] = {
363 test::Pass(embedded_quads
[0], arraysize(embedded_quads
[0]), pass_ids
[0]),
364 test::Pass(embedded_quads
[1], arraysize(embedded_quads
[1]), pass_ids
[1]),
365 test::Pass(embedded_quads
[2], arraysize(embedded_quads
[2]), pass_ids
[2])};
367 SubmitFrame(embedded_passes
, arraysize(embedded_passes
), embedded_surface_id
);
369 test::Quad root_quads
[][2] = {
370 {test::Quad::SolidColorQuad(5), test::Quad::SolidColorQuad(6)},
371 {test::Quad::SurfaceQuad(embedded_surface_id
),
372 test::Quad::RenderPassQuad(pass_ids
[0])},
373 {test::Quad::SolidColorQuad(7), test::Quad::RenderPassQuad(pass_ids
[1])}};
374 test::Pass root_passes
[] = {
375 test::Pass(root_quads
[0], arraysize(root_quads
[0]), pass_ids
[0]),
376 test::Pass(root_quads
[1], arraysize(root_quads
[1]), pass_ids
[1]),
377 test::Pass(root_quads
[2], arraysize(root_quads
[2]), pass_ids
[2])};
379 SubmitFrame(root_passes
, arraysize(root_passes
), root_surface_id_
);
381 scoped_ptr
<CompositorFrame
> aggregated_frame
=
382 aggregator_
.Aggregate(root_surface_id_
);
384 ASSERT_TRUE(aggregated_frame
);
385 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
387 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
389 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
391 ASSERT_EQ(5u, aggregated_pass_list
.size());
392 RenderPassId actual_pass_ids
[] = {
393 aggregated_pass_list
[0]->id
, aggregated_pass_list
[1]->id
,
394 aggregated_pass_list
[2]->id
, aggregated_pass_list
[3]->id
,
395 aggregated_pass_list
[4]->id
};
396 for (size_t i
= 0; i
< 5; ++i
) {
397 for (size_t j
= 0; j
< i
; ++j
) {
398 EXPECT_NE(actual_pass_ids
[i
], actual_pass_ids
[j
]);
403 SCOPED_TRACE("First pass");
404 // The first pass will just be the first pass from the root surfaces quad
405 // with no render pass quads to remap.
406 TestPassMatchesExpectations(root_passes
[0], aggregated_pass_list
[0]);
410 SCOPED_TRACE("Second pass");
411 // The next two passes will be from the embedded surface since we have to
412 // draw those passes before they are referenced from the render pass draw
413 // quad embedded into the root surface's second pass.
414 // First, there's the first embedded pass which doesn't reference anything
416 TestPassMatchesExpectations(embedded_passes
[0], aggregated_pass_list
[1]);
420 SCOPED_TRACE("Third pass");
421 const QuadList
& third_pass_quad_list
= aggregated_pass_list
[2]->quad_list
;
422 ASSERT_EQ(2u, third_pass_quad_list
.size());
423 TestQuadMatchesExpectations(embedded_quads
[1][0],
424 third_pass_quad_list
.ElementAt(0));
426 // This render pass pass quad will reference the first pass from the
427 // embedded surface, which is the second pass in the aggregated frame.
428 ASSERT_EQ(DrawQuad::RENDER_PASS
,
429 third_pass_quad_list
.ElementAt(1)->material
);
430 const RenderPassDrawQuad
* third_pass_render_pass_draw_quad
=
431 RenderPassDrawQuad::MaterialCast(third_pass_quad_list
.ElementAt(1));
432 EXPECT_EQ(actual_pass_ids
[1],
433 third_pass_render_pass_draw_quad
->render_pass_id
);
437 SCOPED_TRACE("Fourth pass");
438 // The fourth pass will have aggregated quads from the root surface's second
439 // pass and the embedded surface's first pass.
440 const QuadList
& fourth_pass_quad_list
= aggregated_pass_list
[3]->quad_list
;
441 ASSERT_EQ(3u, fourth_pass_quad_list
.size());
443 // The first quad will be the yellow quad from the embedded surface's last
445 TestQuadMatchesExpectations(embedded_quads
[2][0],
446 fourth_pass_quad_list
.ElementAt(0));
448 // The next quad will be a render pass quad referencing the second pass from
449 // the embedded surface, which is the third pass in the aggregated frame.
450 ASSERT_EQ(DrawQuad::RENDER_PASS
,
451 fourth_pass_quad_list
.ElementAt(1)->material
);
452 const RenderPassDrawQuad
* fourth_pass_first_render_pass_draw_quad
=
453 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list
.ElementAt(1));
454 EXPECT_EQ(actual_pass_ids
[2],
455 fourth_pass_first_render_pass_draw_quad
->render_pass_id
);
457 // The last quad will be a render pass quad referencing the first pass from
458 // the root surface, which is the first pass overall.
459 ASSERT_EQ(DrawQuad::RENDER_PASS
,
460 fourth_pass_quad_list
.ElementAt(2)->material
);
461 const RenderPassDrawQuad
* fourth_pass_second_render_pass_draw_quad
=
462 RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list
.ElementAt(2));
463 EXPECT_EQ(actual_pass_ids
[0],
464 fourth_pass_second_render_pass_draw_quad
->render_pass_id
);
468 SCOPED_TRACE("Fifth pass");
469 const QuadList
& fifth_pass_quad_list
= aggregated_pass_list
[4]->quad_list
;
470 ASSERT_EQ(2u, fifth_pass_quad_list
.size());
472 TestQuadMatchesExpectations(root_quads
[2][0],
473 fifth_pass_quad_list
.ElementAt(0));
475 // The last quad in the last pass will reference the second pass from the
476 // root surface, which after aggregating is the fourth pass in the overall
478 ASSERT_EQ(DrawQuad::RENDER_PASS
,
479 fifth_pass_quad_list
.ElementAt(1)->material
);
480 const RenderPassDrawQuad
* fifth_pass_render_pass_draw_quad
=
481 RenderPassDrawQuad::MaterialCast(fifth_pass_quad_list
.ElementAt(1));
482 EXPECT_EQ(actual_pass_ids
[3],
483 fifth_pass_render_pass_draw_quad
->render_pass_id
);
485 factory_
.Destroy(embedded_surface_id
);
488 // Tests an invalid surface reference in a frame. The surface quad should just
490 TEST_F(SurfaceAggregatorValidSurfaceTest
, InvalidSurfaceReference
) {
491 test::Quad quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
),
492 test::Quad::SurfaceQuad(InvalidSurfaceId()),
493 test::Quad::SolidColorQuad(SK_ColorBLUE
)};
494 test::Pass passes
[] = {test::Pass(quads
, arraysize(quads
))};
496 SubmitFrame(passes
, arraysize(passes
), root_surface_id_
);
498 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
),
499 test::Quad::SolidColorQuad(SK_ColorBLUE
)};
500 test::Pass expected_passes
[] = {
501 test::Pass(expected_quads
, arraysize(expected_quads
))};
502 SurfaceId ids
[] = {root_surface_id_
, InvalidSurfaceId()};
504 expected_passes
, arraysize(expected_passes
), ids
, arraysize(ids
));
507 // Tests a reference to a valid surface with no submitted frame. This quad
508 // should also just be dropped.
509 TEST_F(SurfaceAggregatorValidSurfaceTest
, ValidSurfaceReferenceWithNoFrame
) {
510 SurfaceId surface_with_no_frame_id
= allocator_
.GenerateId();
511 factory_
.Create(surface_with_no_frame_id
, gfx::Size(5, 5));
512 test::Quad quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
),
513 test::Quad::SurfaceQuad(surface_with_no_frame_id
),
514 test::Quad::SolidColorQuad(SK_ColorBLUE
)};
515 test::Pass passes
[] = {test::Pass(quads
, arraysize(quads
))};
517 SubmitFrame(passes
, arraysize(passes
), root_surface_id_
);
519 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
),
520 test::Quad::SolidColorQuad(SK_ColorBLUE
)};
521 test::Pass expected_passes
[] = {
522 test::Pass(expected_quads
, arraysize(expected_quads
))};
523 SurfaceId ids
[] = {root_surface_id_
, surface_with_no_frame_id
};
525 expected_passes
, arraysize(expected_passes
), ids
, arraysize(ids
));
526 factory_
.Destroy(surface_with_no_frame_id
);
529 // Tests a surface quad referencing itself, generating a trivial cycle.
530 // The quad creating the cycle should be dropped from the final frame.
531 TEST_F(SurfaceAggregatorValidSurfaceTest
, SimpleCyclicalReference
) {
532 test::Quad quads
[] = {test::Quad::SurfaceQuad(root_surface_id_
),
533 test::Quad::SolidColorQuad(SK_ColorYELLOW
)};
534 test::Pass passes
[] = {test::Pass(quads
, arraysize(quads
))};
536 SubmitFrame(passes
, arraysize(passes
), root_surface_id_
);
538 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorYELLOW
)};
539 test::Pass expected_passes
[] = {
540 test::Pass(expected_quads
, arraysize(expected_quads
))};
541 SurfaceId ids
[] = {root_surface_id_
};
543 expected_passes
, arraysize(expected_passes
), ids
, arraysize(ids
));
546 // Tests a more complex cycle with one intermediate surface.
547 TEST_F(SurfaceAggregatorValidSurfaceTest
, TwoSurfaceCyclicalReference
) {
548 SurfaceId child_surface_id
= allocator_
.GenerateId();
549 factory_
.Create(child_surface_id
, SurfaceSize());
551 test::Quad parent_quads
[] = {test::Quad::SolidColorQuad(SK_ColorBLUE
),
552 test::Quad::SurfaceQuad(child_surface_id
),
553 test::Quad::SolidColorQuad(SK_ColorCYAN
)};
554 test::Pass parent_passes
[] = {
555 test::Pass(parent_quads
, arraysize(parent_quads
))};
557 SubmitFrame(parent_passes
, arraysize(parent_passes
), root_surface_id_
);
559 test::Quad child_quads
[] = {test::Quad::SolidColorQuad(SK_ColorGREEN
),
560 test::Quad::SurfaceQuad(root_surface_id_
),
561 test::Quad::SolidColorQuad(SK_ColorMAGENTA
)};
562 test::Pass child_passes
[] = {test::Pass(child_quads
, arraysize(child_quads
))};
564 SubmitFrame(child_passes
, arraysize(child_passes
), child_surface_id
);
566 // The child surface's reference to the root_surface_ will be dropped, so
567 // we'll end up with:
568 // SK_ColorBLUE from the parent
569 // SK_ColorGREEN from the child
570 // SK_ColorMAGENTA from the child
571 // SK_ColorCYAN from the parent
572 test::Quad expected_quads
[] = {test::Quad::SolidColorQuad(SK_ColorBLUE
),
573 test::Quad::SolidColorQuad(SK_ColorGREEN
),
574 test::Quad::SolidColorQuad(SK_ColorMAGENTA
),
575 test::Quad::SolidColorQuad(SK_ColorCYAN
)};
576 test::Pass expected_passes
[] = {
577 test::Pass(expected_quads
, arraysize(expected_quads
))};
578 SurfaceId ids
[] = {root_surface_id_
, child_surface_id
};
580 expected_passes
, arraysize(expected_passes
), ids
, arraysize(ids
));
581 factory_
.Destroy(child_surface_id
);
584 // Tests that we map render pass IDs from different surfaces into a unified
585 // namespace and update RenderPassDrawQuad's id references to match.
586 TEST_F(SurfaceAggregatorValidSurfaceTest
, RenderPassIdMapping
) {
587 SurfaceId child_surface_id
= allocator_
.GenerateId();
588 factory_
.Create(child_surface_id
, SurfaceSize());
590 RenderPassId child_pass_id
[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
591 test::Quad child_quad
[][1] = {{test::Quad::SolidColorQuad(SK_ColorGREEN
)},
592 {test::Quad::RenderPassQuad(child_pass_id
[0])}};
593 test::Pass surface_passes
[] = {
594 test::Pass(child_quad
[0], arraysize(child_quad
[0]), child_pass_id
[0]),
595 test::Pass(child_quad
[1], arraysize(child_quad
[1]), child_pass_id
[1])};
597 SubmitFrame(surface_passes
, arraysize(surface_passes
), child_surface_id
);
599 // Pass IDs from the parent surface may collide with ones from the child.
600 RenderPassId parent_pass_id
[] = {RenderPassId(2, 1), RenderPassId(1, 2)};
601 test::Quad parent_quad
[][1] = {
602 {test::Quad::SurfaceQuad(child_surface_id
)},
603 {test::Quad::RenderPassQuad(parent_pass_id
[0])}};
604 test::Pass parent_passes
[] = {
605 test::Pass(parent_quad
[0], arraysize(parent_quad
[0]), parent_pass_id
[0]),
606 test::Pass(parent_quad
[1], arraysize(parent_quad
[1]), parent_pass_id
[1])};
608 SubmitFrame(parent_passes
, arraysize(parent_passes
), root_surface_id_
);
609 scoped_ptr
<CompositorFrame
> aggregated_frame
=
610 aggregator_
.Aggregate(root_surface_id_
);
612 ASSERT_TRUE(aggregated_frame
);
613 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
615 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
617 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
619 ASSERT_EQ(3u, aggregated_pass_list
.size());
620 RenderPassId actual_pass_ids
[] = {aggregated_pass_list
[0]->id
,
621 aggregated_pass_list
[1]->id
,
622 aggregated_pass_list
[2]->id
};
623 // Make sure the aggregated frame's pass IDs are all unique.
624 for (size_t i
= 0; i
< 3; ++i
) {
625 for (size_t j
= 0; j
< i
; ++j
) {
626 EXPECT_NE(actual_pass_ids
[j
], actual_pass_ids
[i
]) << "pass ids " << i
631 // Make sure the render pass quads reference the remapped pass IDs.
632 DrawQuad
* render_pass_quads
[] = {aggregated_pass_list
[1]->quad_list
.front(),
633 aggregated_pass_list
[2]->quad_list
.front()};
634 ASSERT_EQ(render_pass_quads
[0]->material
, DrawQuad::RENDER_PASS
);
637 RenderPassDrawQuad::MaterialCast(render_pass_quads
[0])->render_pass_id
);
639 ASSERT_EQ(render_pass_quads
[1]->material
, DrawQuad::RENDER_PASS
);
642 RenderPassDrawQuad::MaterialCast(render_pass_quads
[1])->render_pass_id
);
643 factory_
.Destroy(child_surface_id
);
646 void AddSolidColorQuadWithBlendMode(const gfx::Size
& size
,
648 const SkXfermode::Mode blend_mode
) {
649 const gfx::Transform content_to_target_transform
;
650 const gfx::Size
content_bounds(size
);
651 const gfx::Rect
visible_content_rect(size
);
652 const gfx::Rect
clip_rect(size
);
654 bool is_clipped
= false;
657 bool force_anti_aliasing_off
= false;
658 SharedQuadState
* sqs
= pass
->CreateAndAppendSharedQuadState();
659 sqs
->SetAll(content_to_target_transform
,
661 visible_content_rect
,
668 SolidColorDrawQuad
* color_quad
=
669 pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
670 color_quad
->SetNew(pass
->shared_quad_state_list
.back(),
671 visible_content_rect
,
672 visible_content_rect
,
674 force_anti_aliasing_off
);
677 // This tests that we update shared quad state pointers correctly within
678 // aggregated passes. The shared quad state list on the aggregated pass will
679 // include the shared quad states from each pass in one list so the quads will
680 // end up pointed to shared quad state objects at different offsets. This test
681 // uses the blend_mode value stored on the shared quad state to track the shared
682 // quad state, but anything saved on the shared quad state would work.
684 // This test has 4 surfaces in the following structure:
685 // root_surface -> quad with kClear_Mode,
686 // [child_one_surface],
687 // quad with kDstOver_Mode,
688 // [child_two_surface],
689 // quad with kDstIn_Mode
690 // child_one_surface -> quad with kSrc_Mode,
691 // [grandchild_surface],
692 // quad with kSrcOver_Mode
693 // child_two_surface -> quad with kSrcIn_Mode
694 // grandchild_surface -> quad with kDst_Mode
696 // Resulting in the following aggregated pass:
697 // quad_root_0 - blend_mode kClear_Mode
698 // quad_child_one_0 - blend_mode kSrc_Mode
699 // quad_grandchild_0 - blend_mode kDst_Mode
700 // quad_child_one_1 - blend_mode kSrcOver_Mode
701 // quad_root_1 - blend_mode kDstOver_Mode
702 // quad_child_two_0 - blend_mode kSrcIn_Mode
703 // quad_root_2 - blend_mode kDstIn_Mode
704 TEST_F(SurfaceAggregatorValidSurfaceTest
, AggregateSharedQuadStateProperties
) {
705 const SkXfermode::Mode blend_modes
[] = {SkXfermode::kClear_Mode
, // 0
706 SkXfermode::kSrc_Mode
, // 1
707 SkXfermode::kDst_Mode
, // 2
708 SkXfermode::kSrcOver_Mode
, // 3
709 SkXfermode::kDstOver_Mode
, // 4
710 SkXfermode::kSrcIn_Mode
, // 5
711 SkXfermode::kDstIn_Mode
, // 6
714 RenderPassId
pass_id(1, 1);
715 SurfaceId grandchild_surface_id
= allocator_
.GenerateId();
716 factory_
.Create(grandchild_surface_id
, SurfaceSize());
717 scoped_ptr
<RenderPass
> grandchild_pass
= RenderPass::Create();
718 gfx::Rect
output_rect(SurfaceSize());
719 gfx::Rect
damage_rect(SurfaceSize());
720 gfx::Transform transform_to_root_target
;
721 grandchild_pass
->SetNew(
722 pass_id
, output_rect
, damage_rect
, transform_to_root_target
);
723 AddSolidColorQuadWithBlendMode(
724 SurfaceSize(), grandchild_pass
.get(), blend_modes
[2]);
725 QueuePassAsFrame(grandchild_pass
.Pass(), grandchild_surface_id
);
727 SurfaceId child_one_surface_id
= allocator_
.GenerateId();
728 factory_
.Create(child_one_surface_id
, SurfaceSize());
730 scoped_ptr
<RenderPass
> child_one_pass
= RenderPass::Create();
731 child_one_pass
->SetNew(
732 pass_id
, output_rect
, damage_rect
, transform_to_root_target
);
733 AddSolidColorQuadWithBlendMode(
734 SurfaceSize(), child_one_pass
.get(), blend_modes
[1]);
735 SurfaceDrawQuad
* grandchild_surface_quad
=
736 child_one_pass
->CreateAndAppendDrawQuad
<SurfaceDrawQuad
>();
737 grandchild_surface_quad
->SetNew(child_one_pass
->shared_quad_state_list
.back(),
738 gfx::Rect(SurfaceSize()),
739 gfx::Rect(SurfaceSize()),
740 grandchild_surface_id
);
741 AddSolidColorQuadWithBlendMode(
742 SurfaceSize(), child_one_pass
.get(), blend_modes
[3]);
743 QueuePassAsFrame(child_one_pass
.Pass(), child_one_surface_id
);
745 SurfaceId child_two_surface_id
= allocator_
.GenerateId();
746 factory_
.Create(child_two_surface_id
, SurfaceSize());
748 scoped_ptr
<RenderPass
> child_two_pass
= RenderPass::Create();
749 child_two_pass
->SetNew(
750 pass_id
, output_rect
, damage_rect
, transform_to_root_target
);
751 AddSolidColorQuadWithBlendMode(
752 SurfaceSize(), child_two_pass
.get(), blend_modes
[5]);
753 QueuePassAsFrame(child_two_pass
.Pass(), child_two_surface_id
);
755 scoped_ptr
<RenderPass
> root_pass
= RenderPass::Create();
757 pass_id
, output_rect
, damage_rect
, transform_to_root_target
);
759 AddSolidColorQuadWithBlendMode(
760 SurfaceSize(), root_pass
.get(), blend_modes
[0]);
761 SurfaceDrawQuad
* child_one_surface_quad
=
762 root_pass
->CreateAndAppendDrawQuad
<SurfaceDrawQuad
>();
763 child_one_surface_quad
->SetNew(root_pass
->shared_quad_state_list
.back(),
764 gfx::Rect(SurfaceSize()),
765 gfx::Rect(SurfaceSize()),
766 child_one_surface_id
);
767 AddSolidColorQuadWithBlendMode(
768 SurfaceSize(), root_pass
.get(), blend_modes
[4]);
769 SurfaceDrawQuad
* child_two_surface_quad
=
770 root_pass
->CreateAndAppendDrawQuad
<SurfaceDrawQuad
>();
771 child_two_surface_quad
->SetNew(root_pass
->shared_quad_state_list
.back(),
772 gfx::Rect(SurfaceSize()),
773 gfx::Rect(SurfaceSize()),
774 child_two_surface_id
);
775 AddSolidColorQuadWithBlendMode(
776 SurfaceSize(), root_pass
.get(), blend_modes
[6]);
778 QueuePassAsFrame(root_pass
.Pass(), root_surface_id_
);
780 scoped_ptr
<CompositorFrame
> aggregated_frame
=
781 aggregator_
.Aggregate(root_surface_id_
);
783 ASSERT_TRUE(aggregated_frame
);
784 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
786 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
788 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
790 ASSERT_EQ(1u, aggregated_pass_list
.size());
792 const QuadList
& aggregated_quad_list
= aggregated_pass_list
[0]->quad_list
;
794 ASSERT_EQ(7u, aggregated_quad_list
.size());
796 for (auto iter
= aggregated_quad_list
.cbegin();
797 iter
!= aggregated_quad_list
.cend();
799 EXPECT_EQ(blend_modes
[iter
.index()], iter
->shared_quad_state
->blend_mode
)
802 factory_
.Destroy(child_one_surface_id
);
803 factory_
.Destroy(child_two_surface_id
);
804 factory_
.Destroy(grandchild_surface_id
);
807 // This tests that when aggregating a frame with multiple render passes that we
808 // map the transforms for the root pass but do not modify the transform on child
811 // The root surface has one pass with a surface quad transformed by +10 in the y
814 // The child surface has two passes. The first pass has a quad with a transform
815 // of +5 in the x direction. The second pass has a reference to the first pass'
816 // pass id and a transform of +8 in the x direction.
818 // After aggregation, the child surface's root pass quad should have both
819 // transforms concatenated for a total transform of +8 x, +10 y. The
820 // contributing render pass' transform in the aggregate frame should not be
822 TEST_F(SurfaceAggregatorValidSurfaceTest
, AggregateMultiplePassWithTransform
) {
823 SurfaceId child_surface_id
= allocator_
.GenerateId();
824 factory_
.Create(child_surface_id
, SurfaceSize());
825 RenderPassId child_pass_id
[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
826 test::Quad child_quads
[][1] = {
827 {test::Quad::SolidColorQuad(SK_ColorGREEN
)},
828 {test::Quad::RenderPassQuad(child_pass_id
[0])}};
829 test::Pass child_passes
[] = {
830 test::Pass(child_quads
[0], arraysize(child_quads
[0]), child_pass_id
[0]),
831 test::Pass(child_quads
[1], arraysize(child_quads
[1]), child_pass_id
[1])};
833 RenderPassList child_pass_list
;
834 AddPasses(&child_pass_list
,
835 gfx::Rect(SurfaceSize()),
837 arraysize(child_passes
));
839 RenderPass
* child_nonroot_pass
= child_pass_list
.at(0u);
840 child_nonroot_pass
->transform_to_root_target
.Translate(8, 0);
841 SharedQuadState
* child_nonroot_pass_sqs
=
842 child_nonroot_pass
->shared_quad_state_list
.front();
843 child_nonroot_pass_sqs
->content_to_target_transform
.Translate(5, 0);
845 RenderPass
* child_root_pass
= child_pass_list
.at(1u);
846 SharedQuadState
* child_root_pass_sqs
=
847 child_root_pass
->shared_quad_state_list
.front();
848 child_root_pass_sqs
->content_to_target_transform
.Translate(8, 0);
849 child_root_pass_sqs
->is_clipped
= true;
850 child_root_pass_sqs
->clip_rect
= gfx::Rect(0, 0, 5, 5);
852 scoped_ptr
<DelegatedFrameData
> child_frame_data(new DelegatedFrameData
);
853 child_pass_list
.swap(child_frame_data
->render_pass_list
);
855 scoped_ptr
<CompositorFrame
> child_frame(new CompositorFrame
);
856 child_frame
->delegated_frame_data
= child_frame_data
.Pass();
858 factory_
.SubmitFrame(child_surface_id
, child_frame
.Pass(), base::Closure());
860 test::Quad root_quads
[] = {test::Quad::SolidColorQuad(1),
861 test::Quad::SurfaceQuad(child_surface_id
)};
862 test::Pass root_passes
[] = {test::Pass(root_quads
, arraysize(root_quads
))};
864 RenderPassList root_pass_list
;
865 AddPasses(&root_pass_list
,
866 gfx::Rect(SurfaceSize()),
868 arraysize(root_passes
));
871 ->shared_quad_state_list
.front()
872 ->content_to_target_transform
.Translate(0, 7);
874 ->shared_quad_state_list
.ElementAt(1)
875 ->content_to_target_transform
.Translate(0, 10);
877 scoped_ptr
<DelegatedFrameData
> root_frame_data(new DelegatedFrameData
);
878 root_pass_list
.swap(root_frame_data
->render_pass_list
);
880 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
881 root_frame
->delegated_frame_data
= root_frame_data
.Pass();
883 factory_
.SubmitFrame(root_surface_id_
, root_frame
.Pass(), base::Closure());
885 scoped_ptr
<CompositorFrame
> aggregated_frame
=
886 aggregator_
.Aggregate(root_surface_id_
);
888 ASSERT_TRUE(aggregated_frame
);
889 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
891 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
893 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
895 ASSERT_EQ(2u, aggregated_pass_list
.size());
897 ASSERT_EQ(1u, aggregated_pass_list
[0]->shared_quad_state_list
.size());
899 // The first pass should have one shared quad state for the one solid color
901 EXPECT_EQ(1u, aggregated_pass_list
[0]->shared_quad_state_list
.size());
902 // The second (root) pass should have just two shared quad states. We'll
903 // verify the properties through the quads.
904 EXPECT_EQ(2u, aggregated_pass_list
[1]->shared_quad_state_list
.size());
906 SharedQuadState
* aggregated_first_pass_sqs
=
907 aggregated_pass_list
[0]->shared_quad_state_list
.front();
909 // The first pass's transform should be unaffected by the embedding and still
910 // be a translation by +5 in the x direction.
911 gfx::Transform expected_aggregated_first_pass_sqs_transform
;
912 expected_aggregated_first_pass_sqs_transform
.Translate(5, 0);
913 EXPECT_EQ(expected_aggregated_first_pass_sqs_transform
.ToString(),
914 aggregated_first_pass_sqs
->content_to_target_transform
.ToString());
916 // The first pass's transform to the root target should include the aggregated
918 gfx::Transform expected_first_pass_transform_to_root_target
;
919 expected_first_pass_transform_to_root_target
.Translate(8, 10);
920 EXPECT_EQ(expected_first_pass_transform_to_root_target
.ToString(),
921 aggregated_pass_list
[0]->transform_to_root_target
.ToString());
923 ASSERT_EQ(2u, aggregated_pass_list
[1]->quad_list
.size());
925 gfx::Transform expected_root_pass_quad_transforms
[2];
926 // The first quad in the root pass is the solid color quad from the original
927 // root surface. Its transform should be unaffected by the aggregation and
928 // still be +7 in the y direction.
929 expected_root_pass_quad_transforms
[0].Translate(0, 7);
930 // The second quad in the root pass is aggregated from the child surface so
931 // its transform should be the combination of its original translation (0, 10)
932 // and the child surface draw quad's translation (8, 0).
933 expected_root_pass_quad_transforms
[1].Translate(8, 10);
935 for (auto iter
= aggregated_pass_list
[1]->quad_list
.cbegin();
936 iter
!= aggregated_pass_list
[1]->quad_list
.cend();
938 EXPECT_EQ(expected_root_pass_quad_transforms
[iter
.index()].ToString(),
939 iter
->quadTransform().ToString())
944 aggregated_pass_list
[1]->shared_quad_state_list
.ElementAt(1)->is_clipped
);
946 // The second quad in the root pass is aggregated from the child, so its
947 // clip rect must be transformed by the child's translation.
948 EXPECT_EQ(gfx::Rect(0, 10, 5, 5).ToString(),
949 aggregated_pass_list
[1]
950 ->shared_quad_state_list
.ElementAt(1)
951 ->clip_rect
.ToString());
953 factory_
.Destroy(child_surface_id
);
956 // Tests that damage rects are aggregated correctly when surfaces change.
957 TEST_F(SurfaceAggregatorValidSurfaceTest
, AggregateDamageRect
) {
958 SurfaceId child_surface_id
= allocator_
.GenerateId();
959 factory_
.Create(child_surface_id
, SurfaceSize());
960 RenderPassId child_pass_id
= RenderPassId(1, 1);
961 test::Quad child_quads
[] = {test::Quad::RenderPassQuad(child_pass_id
)};
962 test::Pass child_passes
[] = {
963 test::Pass(child_quads
, arraysize(child_quads
), child_pass_id
)};
965 RenderPassList child_pass_list
;
966 AddPasses(&child_pass_list
,
967 gfx::Rect(SurfaceSize()),
969 arraysize(child_passes
));
971 RenderPass
* child_root_pass
= child_pass_list
.at(0u);
972 SharedQuadState
* child_root_pass_sqs
=
973 child_root_pass
->shared_quad_state_list
.front();
974 child_root_pass_sqs
->content_to_target_transform
.Translate(8, 0);
976 scoped_ptr
<DelegatedFrameData
> child_frame_data(new DelegatedFrameData
);
977 child_pass_list
.swap(child_frame_data
->render_pass_list
);
979 scoped_ptr
<CompositorFrame
> child_frame(new CompositorFrame
);
980 child_frame
->delegated_frame_data
= child_frame_data
.Pass();
982 factory_
.SubmitFrame(child_surface_id
, child_frame
.Pass(), base::Closure());
984 test::Quad root_quads
[] = {test::Quad::SurfaceQuad(child_surface_id
)};
985 test::Pass root_passes
[] = {test::Pass(root_quads
, arraysize(root_quads
))};
987 RenderPassList root_pass_list
;
988 AddPasses(&root_pass_list
,
989 gfx::Rect(SurfaceSize()),
991 arraysize(root_passes
));
994 ->shared_quad_state_list
.front()
995 ->content_to_target_transform
.Translate(0, 10);
996 root_pass_list
.at(0)->damage_rect
= gfx::Rect(5, 5, 10, 10);
998 scoped_ptr
<DelegatedFrameData
> root_frame_data(new DelegatedFrameData
);
999 root_pass_list
.swap(root_frame_data
->render_pass_list
);
1001 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
1002 root_frame
->delegated_frame_data
= root_frame_data
.Pass();
1004 factory_
.SubmitFrame(root_surface_id_
, root_frame
.Pass(), base::Closure());
1006 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1007 aggregator_
.Aggregate(root_surface_id_
);
1009 ASSERT_TRUE(aggregated_frame
);
1010 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1012 DelegatedFrameData
* frame_data
= aggregated_frame
->delegated_frame_data
.get();
1014 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1016 ASSERT_EQ(1u, aggregated_pass_list
.size());
1018 // Damage rect for first aggregation should contain entire root surface.
1020 aggregated_pass_list
[0]->damage_rect
.Contains(gfx::Rect(SurfaceSize())));
1023 AddPasses(&child_pass_list
,
1024 gfx::Rect(SurfaceSize()),
1026 arraysize(child_passes
));
1028 RenderPass
* child_root_pass
= child_pass_list
.at(0u);
1029 SharedQuadState
* child_root_pass_sqs
=
1030 child_root_pass
->shared_quad_state_list
.front();
1031 child_root_pass_sqs
->content_to_target_transform
.Translate(8, 0);
1032 child_root_pass
->damage_rect
= gfx::Rect(10, 10, 10, 10);
1034 scoped_ptr
<DelegatedFrameData
> child_frame_data(new DelegatedFrameData
);
1035 child_pass_list
.swap(child_frame_data
->render_pass_list
);
1037 scoped_ptr
<CompositorFrame
> child_frame(new CompositorFrame
);
1038 child_frame
->delegated_frame_data
= child_frame_data
.Pass();
1040 factory_
.SubmitFrame(child_surface_id
, child_frame
.Pass(), base::Closure());
1042 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1043 aggregator_
.Aggregate(root_surface_id_
);
1045 ASSERT_TRUE(aggregated_frame
);
1046 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1048 DelegatedFrameData
* frame_data
=
1049 aggregated_frame
->delegated_frame_data
.get();
1051 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1053 ASSERT_EQ(1u, aggregated_pass_list
.size());
1055 // Outer surface didn't change, so transformed inner damage rect should be
1057 EXPECT_EQ(gfx::Rect(10, 20, 10, 10).ToString(),
1058 aggregated_pass_list
[0]->damage_rect
.ToString());
1062 RenderPassList root_pass_list
;
1063 AddPasses(&root_pass_list
,
1064 gfx::Rect(SurfaceSize()),
1066 arraysize(root_passes
));
1068 root_pass_list
.at(0)
1069 ->shared_quad_state_list
.front()
1070 ->content_to_target_transform
.Translate(0, 10);
1071 root_pass_list
.at(0)->damage_rect
= gfx::Rect(0, 0, 1, 1);
1073 scoped_ptr
<DelegatedFrameData
> root_frame_data(new DelegatedFrameData
);
1074 root_pass_list
.swap(root_frame_data
->render_pass_list
);
1076 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
1077 root_frame
->delegated_frame_data
= root_frame_data
.Pass();
1079 factory_
.SubmitFrame(root_surface_id_
, root_frame
.Pass(), base::Closure());
1083 RenderPassList root_pass_list
;
1084 AddPasses(&root_pass_list
,
1085 gfx::Rect(SurfaceSize()),
1087 arraysize(root_passes
));
1089 root_pass_list
.at(0)
1090 ->shared_quad_state_list
.front()
1091 ->content_to_target_transform
.Translate(0, 10);
1092 root_pass_list
.at(0)->damage_rect
= gfx::Rect(1, 1, 1, 1);
1094 scoped_ptr
<DelegatedFrameData
> root_frame_data(new DelegatedFrameData
);
1095 root_pass_list
.swap(root_frame_data
->render_pass_list
);
1097 scoped_ptr
<CompositorFrame
> root_frame(new CompositorFrame
);
1098 root_frame
->delegated_frame_data
= root_frame_data
.Pass();
1100 factory_
.SubmitFrame(root_surface_id_
, root_frame
.Pass(), base::Closure());
1102 scoped_ptr
<CompositorFrame
> aggregated_frame
=
1103 aggregator_
.Aggregate(root_surface_id_
);
1105 ASSERT_TRUE(aggregated_frame
);
1106 ASSERT_TRUE(aggregated_frame
->delegated_frame_data
);
1108 DelegatedFrameData
* frame_data
=
1109 aggregated_frame
->delegated_frame_data
.get();
1111 const RenderPassList
& aggregated_pass_list
= frame_data
->render_pass_list
;
1113 ASSERT_EQ(1u, aggregated_pass_list
.size());
1115 // The root surface was enqueued without being aggregated once, so it should
1116 // be treated as completely damaged.
1117 EXPECT_TRUE(aggregated_pass_list
[0]->damage_rect
.Contains(
1118 gfx::Rect(SurfaceSize())));
1121 factory_
.Destroy(child_surface_id
);
1124 class SurfaceAggregatorWithResourcesTest
: public testing::Test
{
1126 virtual void SetUp() {
1127 output_surface_
= FakeOutputSurface::CreateSoftware(
1128 make_scoped_ptr(new SoftwareOutputDevice
));
1129 output_surface_
->BindToClient(&output_surface_client_
);
1130 shared_bitmap_manager_
.reset(new TestSharedBitmapManager
);
1132 resource_provider_
= ResourceProvider::Create(output_surface_
.get(),
1133 shared_bitmap_manager_
.get(),
1141 new SurfaceAggregator(&manager_
, resource_provider_
.get()));
1145 SurfaceManager manager_
;
1146 FakeOutputSurfaceClient output_surface_client_
;
1147 scoped_ptr
<OutputSurface
> output_surface_
;
1148 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
1149 scoped_ptr
<ResourceProvider
> resource_provider_
;
1150 scoped_ptr
<SurfaceAggregator
> aggregator_
;
1153 class ResourceTrackingSurfaceFactoryClient
: public SurfaceFactoryClient
{
1155 ResourceTrackingSurfaceFactoryClient() {}
1156 ~ResourceTrackingSurfaceFactoryClient() override
{}
1158 void ReturnResources(const ReturnedResourceArray
& resources
) override
{
1159 returned_resources_
= resources
;
1162 ReturnedResourceArray
returned_resources() const {
1163 return returned_resources_
;
1167 ReturnedResourceArray returned_resources_
;
1169 DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient
);
1172 void SubmitFrameWithResources(ResourceProvider::ResourceId
* resource_ids
,
1173 size_t num_resource_ids
,
1174 SurfaceFactory
* factory
,
1175 SurfaceId surface_id
) {
1176 scoped_ptr
<DelegatedFrameData
> frame_data(new DelegatedFrameData
);
1177 scoped_ptr
<RenderPass
> pass
= RenderPass::Create();
1178 pass
->id
= RenderPassId(1, 1);
1179 SharedQuadState
* sqs
= pass
->CreateAndAppendSharedQuadState();
1180 for (size_t i
= 0u; i
< num_resource_ids
; ++i
) {
1181 TransferableResource resource
;
1182 resource
.id
= resource_ids
[i
];
1183 resource
.is_software
= true;
1184 frame_data
->resource_list
.push_back(resource
);
1185 TextureDrawQuad
* quad
= pass
->CreateAndAppendDrawQuad
<TextureDrawQuad
>();
1186 const gfx::Rect rect
;
1187 const gfx::Rect opaque_rect
;
1188 const gfx::Rect visible_rect
;
1189 bool needs_blending
= false;
1190 bool premultiplied_alpha
= false;
1191 const gfx::PointF uv_top_left
;
1192 const gfx::PointF uv_bottom_right
;
1193 SkColor background_color
= SK_ColorGREEN
;
1194 const float vertex_opacity
[4] = {0.f
, 0.f
, 1.f
, 1.f
};
1195 bool flipped
= false;
1202 premultiplied_alpha
,
1209 quad
->shared_quad_state
= sqs
;
1211 frame_data
->render_pass_list
.push_back(pass
.Pass());
1212 scoped_ptr
<CompositorFrame
> frame(new CompositorFrame
);
1213 frame
->delegated_frame_data
= frame_data
.Pass();
1214 factory
->SubmitFrame(surface_id
, frame
.Pass(), base::Closure());
1217 TEST_F(SurfaceAggregatorWithResourcesTest
, TakeResourcesOneSurface
) {
1218 ResourceTrackingSurfaceFactoryClient client
;
1219 SurfaceFactory
factory(&manager_
, &client
);
1220 SurfaceId
surface_id(7u);
1221 factory
.Create(surface_id
, SurfaceSize());
1223 ResourceProvider::ResourceId ids
[] = {11, 12, 13};
1224 SubmitFrameWithResources(ids
, arraysize(ids
), &factory
, surface_id
);
1226 scoped_ptr
<CompositorFrame
> frame
= aggregator_
->Aggregate(surface_id
);
1228 // Nothing should be available to be returned yet.
1229 EXPECT_TRUE(client
.returned_resources().empty());
1231 SubmitFrameWithResources(NULL
, 0u, &factory
, surface_id
);
1233 frame
= aggregator_
->Aggregate(surface_id
);
1235 ASSERT_EQ(3u, client
.returned_resources().size());
1236 ResourceProvider::ResourceId returned_ids
[3];
1237 for (size_t i
= 0; i
< 3; ++i
) {
1238 returned_ids
[i
] = client
.returned_resources()[i
].id
;
1240 EXPECT_THAT(returned_ids
,
1241 testing::WhenSorted(testing::ElementsAreArray(ids
)));
1242 factory
.Destroy(surface_id
);