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