Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / cc / surfaces / surface_aggregator_unittest.cc
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.
4
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"
28
29 namespace cc {
30 namespace {
31
32 SurfaceId InvalidSurfaceId() {
33   static SurfaceId invalid;
34   invalid.id = static_cast<uint64_t>(-1);
35   return invalid;
36 }
37
38 gfx::Size SurfaceSize() {
39   static gfx::Size size(5, 5);
40   return size;
41 }
42
43 class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
44  public:
45   virtual void ReturnResources(
46       const ReturnedResourceArray& resources) OVERRIDE {}
47 };
48
49 class SurfaceAggregatorTest : public testing::Test {
50  public:
51   SurfaceAggregatorTest()
52       : factory_(&manager_, &empty_client_), aggregator_(&manager_, NULL) {}
53
54  protected:
55   SurfaceManager manager_;
56   EmptySurfaceFactoryClient empty_client_;
57   SurfaceFactory factory_;
58   SurfaceAggregator aggregator_;
59 };
60
61 TEST_F(SurfaceAggregatorTest, ValidSurfaceNoFrame) {
62   SurfaceId one_id(7);
63   factory_.Create(one_id, SurfaceSize());
64   scoped_ptr<CompositorFrame> frame = aggregator_.Aggregate(one_id);
65   EXPECT_FALSE(frame);
66   factory_.Destroy(one_id);
67 }
68
69 class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
70  public:
71   SurfaceAggregatorValidSurfaceTest() : allocator_(1u) {}
72
73   virtual void SetUp() {
74     SurfaceAggregatorTest::SetUp();
75     root_surface_id_ = allocator_.GenerateId();
76     factory_.Create(root_surface_id_, SurfaceSize());
77   }
78
79   virtual void TearDown() {
80     factory_.Destroy(root_surface_id_);
81     SurfaceAggregatorTest::TearDown();
82   }
83
84   void AggregateAndVerify(test::Pass* expected_passes,
85                           size_t expected_pass_count,
86                           SurfaceId* surface_ids,
87                           size_t expected_surface_count) {
88     scoped_ptr<CompositorFrame> aggregated_frame =
89         aggregator_.Aggregate(root_surface_id_);
90
91     ASSERT_TRUE(aggregated_frame);
92     ASSERT_TRUE(aggregated_frame->delegated_frame_data);
93
94     DelegatedFrameData* frame_data =
95         aggregated_frame->delegated_frame_data.get();
96
97     TestPassesMatchExpectations(
98         expected_passes, expected_pass_count, &frame_data->render_pass_list);
99
100     EXPECT_EQ(expected_surface_count,
101               aggregator_.previous_contained_surfaces().size());
102     for (size_t i = 0; i < expected_surface_count; i++) {
103       EXPECT_TRUE(
104           aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
105           aggregator_.previous_contained_surfaces().end());
106     }
107   }
108
109   void SubmitFrame(test::Pass* passes,
110                    size_t pass_count,
111                    SurfaceId surface_id) {
112     RenderPassList pass_list;
113     AddPasses(&pass_list, gfx::Rect(SurfaceSize()), passes, pass_count);
114
115     scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
116     pass_list.swap(frame_data->render_pass_list);
117
118     scoped_ptr<CompositorFrame> frame(new CompositorFrame);
119     frame->delegated_frame_data = frame_data.Pass();
120
121     factory_.SubmitFrame(surface_id, frame.Pass(), base::Closure());
122   }
123
124   void QueuePassAsFrame(scoped_ptr<RenderPass> pass, SurfaceId surface_id) {
125     scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
126     delegated_frame_data->render_pass_list.push_back(pass.Pass());
127
128     scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
129     child_frame->delegated_frame_data = delegated_frame_data.Pass();
130
131     factory_.SubmitFrame(surface_id, child_frame.Pass(), base::Closure());
132   }
133
134  protected:
135   SurfaceId root_surface_id_;
136   SurfaceIdAllocator allocator_;
137 };
138
139 // Tests that a very simple frame containing only two solid color quads makes it
140 // through the aggregator correctly.
141 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) {
142   test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorRED),
143                         test::Quad::SolidColorQuad(SK_ColorBLUE)};
144   test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
145
146   SubmitFrame(passes, arraysize(passes), root_surface_id_);
147
148   SurfaceId ids[] = {root_surface_id_};
149   AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids));
150 }
151
152 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {
153   test::Quad quads[][2] = {{test::Quad::SolidColorQuad(SK_ColorWHITE),
154                             test::Quad::SolidColorQuad(SK_ColorLTGRAY)},
155                            {test::Quad::SolidColorQuad(SK_ColorGRAY),
156                             test::Quad::SolidColorQuad(SK_ColorDKGRAY)}};
157   test::Pass passes[] = {test::Pass(quads[0], arraysize(quads[0])),
158                          test::Pass(quads[1], arraysize(quads[1]))};
159
160   SubmitFrame(passes, arraysize(passes), root_surface_id_);
161
162   SurfaceId ids[] = {root_surface_id_};
163   AggregateAndVerify(passes, arraysize(passes), ids, arraysize(ids));
164 }
165
166 // This tests very simple embedding. root_surface has a frame containing a few
167 // solid color quads and a surface quad referencing embedded_surface.
168 // embedded_surface has a frame containing only a solid color quad. The solid
169 // color quad should be aggregated into the final frame.
170 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
171   SurfaceId embedded_surface_id = allocator_.GenerateId();
172   factory_.Create(embedded_surface_id, SurfaceSize());
173
174   test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
175   test::Pass embedded_passes[] = {
176       test::Pass(embedded_quads, arraysize(embedded_quads))};
177
178   SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
179
180   test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
181                              test::Quad::SurfaceQuad(embedded_surface_id),
182                              test::Quad::SolidColorQuad(SK_ColorBLACK)};
183   test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
184
185   SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
186
187   test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
188                                  test::Quad::SolidColorQuad(SK_ColorGREEN),
189                                  test::Quad::SolidColorQuad(SK_ColorBLACK)};
190   test::Pass expected_passes[] = {
191       test::Pass(expected_quads, arraysize(expected_quads))};
192   SurfaceId ids[] = {root_surface_id_, embedded_surface_id};
193   AggregateAndVerify(
194       expected_passes, arraysize(expected_passes), ids, arraysize(ids));
195
196   factory_.Destroy(embedded_surface_id);
197 }
198
199 TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
200   SurfaceId embedded_surface_id = allocator_.GenerateId();
201   factory_.Create(embedded_surface_id, SurfaceSize());
202
203   test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
204   test::Pass embedded_passes[] = {
205       test::Pass(embedded_quads, arraysize(embedded_quads))};
206
207   SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
208   scoped_ptr<CopyOutputRequest> copy_request(
209       CopyOutputRequest::CreateEmptyRequest());
210   CopyOutputRequest* copy_request_ptr = copy_request.get();
211   factory_.RequestCopyOfSurface(embedded_surface_id, copy_request.Pass());
212
213   test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
214                              test::Quad::SurfaceQuad(embedded_surface_id),
215                              test::Quad::SolidColorQuad(SK_ColorBLACK)};
216   test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
217
218   SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
219
220   scoped_ptr<CompositorFrame> aggregated_frame =
221       aggregator_.Aggregate(root_surface_id_);
222
223   ASSERT_TRUE(aggregated_frame);
224   ASSERT_TRUE(aggregated_frame->delegated_frame_data);
225
226   DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
227
228   test::Quad expected_quads[] = {
229       test::Quad::SolidColorQuad(SK_ColorWHITE),
230       test::Quad::RenderPassQuad(frame_data->render_pass_list[0]->id),
231       test::Quad::SolidColorQuad(SK_ColorBLACK)};
232   test::Pass expected_passes[] = {
233       test::Pass(embedded_quads, arraysize(embedded_quads)),
234       test::Pass(expected_quads, arraysize(expected_quads))};
235   TestPassesMatchExpectations(expected_passes,
236                               arraysize(expected_passes),
237                               &frame_data->render_pass_list);
238   ASSERT_EQ(2u, frame_data->render_pass_list.size());
239   ASSERT_EQ(1u, frame_data->render_pass_list[0]->copy_requests.size());
240   DCHECK_EQ(copy_request_ptr,
241             frame_data->render_pass_list[0]->copy_requests[0]);
242
243   SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id};
244   EXPECT_EQ(arraysize(surface_ids),
245             aggregator_.previous_contained_surfaces().size());
246   for (size_t i = 0; i < arraysize(surface_ids); i++) {
247     EXPECT_TRUE(
248         aggregator_.previous_contained_surfaces().find(surface_ids[i]) !=
249         aggregator_.previous_contained_surfaces().end());
250   }
251
252   factory_.Destroy(embedded_surface_id);
253 }
254
255 // This tests referencing a surface that has multiple render passes.
256 TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
257   SurfaceId embedded_surface_id = allocator_.GenerateId();
258   factory_.Create(embedded_surface_id, SurfaceSize());
259
260   RenderPassId pass_ids[] = {RenderPassId(1, 1), RenderPassId(1, 2),
261                              RenderPassId(1, 3)};
262
263   test::Quad embedded_quads[][2] = {
264       {test::Quad::SolidColorQuad(1), test::Quad::SolidColorQuad(2)},
265       {test::Quad::SolidColorQuad(3), test::Quad::RenderPassQuad(pass_ids[0])},
266       {test::Quad::SolidColorQuad(4), test::Quad::RenderPassQuad(pass_ids[1])}};
267   test::Pass embedded_passes[] = {
268       test::Pass(embedded_quads[0], arraysize(embedded_quads[0]), pass_ids[0]),
269       test::Pass(embedded_quads[1], arraysize(embedded_quads[1]), pass_ids[1]),
270       test::Pass(embedded_quads[2], arraysize(embedded_quads[2]), pass_ids[2])};
271
272   SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
273
274   test::Quad root_quads[][2] = {
275       {test::Quad::SolidColorQuad(5), test::Quad::SolidColorQuad(6)},
276       {test::Quad::SurfaceQuad(embedded_surface_id),
277        test::Quad::RenderPassQuad(pass_ids[0])},
278       {test::Quad::SolidColorQuad(7), test::Quad::RenderPassQuad(pass_ids[1])}};
279   test::Pass root_passes[] = {
280       test::Pass(root_quads[0], arraysize(root_quads[0]), pass_ids[0]),
281       test::Pass(root_quads[1], arraysize(root_quads[1]), pass_ids[1]),
282       test::Pass(root_quads[2], arraysize(root_quads[2]), pass_ids[2])};
283
284   SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
285
286   scoped_ptr<CompositorFrame> aggregated_frame =
287       aggregator_.Aggregate(root_surface_id_);
288
289   ASSERT_TRUE(aggregated_frame);
290   ASSERT_TRUE(aggregated_frame->delegated_frame_data);
291
292   DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
293
294   const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
295
296   ASSERT_EQ(5u, aggregated_pass_list.size());
297   RenderPassId actual_pass_ids[] = {
298       aggregated_pass_list[0]->id, aggregated_pass_list[1]->id,
299       aggregated_pass_list[2]->id, aggregated_pass_list[3]->id,
300       aggregated_pass_list[4]->id};
301   for (size_t i = 0; i < 5; ++i) {
302     for (size_t j = 0; j < i; ++j) {
303       EXPECT_NE(actual_pass_ids[i], actual_pass_ids[j]);
304     }
305   }
306
307   {
308     SCOPED_TRACE("First pass");
309     // The first pass will just be the first pass from the root surfaces quad
310     // with no render pass quads to remap.
311     TestPassMatchesExpectations(root_passes[0], aggregated_pass_list[0]);
312   }
313
314   {
315     SCOPED_TRACE("Second pass");
316     // The next two passes will be from the embedded surface since we have to
317     // draw those passes before they are referenced from the render pass draw
318     // quad embedded into the root surface's second pass.
319     // First, there's the first embedded pass which doesn't reference anything
320     // else.
321     TestPassMatchesExpectations(embedded_passes[0], aggregated_pass_list[1]);
322   }
323
324   {
325     SCOPED_TRACE("Third pass");
326     const QuadList& third_pass_quad_list = aggregated_pass_list[2]->quad_list;
327     ASSERT_EQ(2u, third_pass_quad_list.size());
328     TestQuadMatchesExpectations(embedded_quads[1][0],
329                                 third_pass_quad_list.ElementAt(0));
330
331     // This render pass pass quad will reference the first pass from the
332     // embedded surface, which is the second pass in the aggregated frame.
333     ASSERT_EQ(DrawQuad::RENDER_PASS,
334               third_pass_quad_list.ElementAt(1)->material);
335     const RenderPassDrawQuad* third_pass_render_pass_draw_quad =
336         RenderPassDrawQuad::MaterialCast(third_pass_quad_list.ElementAt(1));
337     EXPECT_EQ(actual_pass_ids[1],
338               third_pass_render_pass_draw_quad->render_pass_id);
339   }
340
341   {
342     SCOPED_TRACE("Fourth pass");
343     // The fourth pass will have aggregated quads from the root surface's second
344     // pass and the embedded surface's first pass.
345     const QuadList& fourth_pass_quad_list = aggregated_pass_list[3]->quad_list;
346     ASSERT_EQ(3u, fourth_pass_quad_list.size());
347
348     // The first quad will be the yellow quad from the embedded surface's last
349     // pass.
350     TestQuadMatchesExpectations(embedded_quads[2][0],
351                                 fourth_pass_quad_list.ElementAt(0));
352
353     // The next quad will be a render pass quad referencing the second pass from
354     // the embedded surface, which is the third pass in the aggregated frame.
355     ASSERT_EQ(DrawQuad::RENDER_PASS,
356               fourth_pass_quad_list.ElementAt(1)->material);
357     const RenderPassDrawQuad* fourth_pass_first_render_pass_draw_quad =
358         RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.ElementAt(1));
359     EXPECT_EQ(actual_pass_ids[2],
360               fourth_pass_first_render_pass_draw_quad->render_pass_id);
361
362     // The last quad will be a render pass quad referencing the first pass from
363     // the root surface, which is the first pass overall.
364     ASSERT_EQ(DrawQuad::RENDER_PASS,
365               fourth_pass_quad_list.ElementAt(2)->material);
366     const RenderPassDrawQuad* fourth_pass_second_render_pass_draw_quad =
367         RenderPassDrawQuad::MaterialCast(fourth_pass_quad_list.ElementAt(2));
368     EXPECT_EQ(actual_pass_ids[0],
369               fourth_pass_second_render_pass_draw_quad->render_pass_id);
370   }
371
372   {
373     SCOPED_TRACE("Fifth pass");
374     const QuadList& fifth_pass_quad_list = aggregated_pass_list[4]->quad_list;
375     ASSERT_EQ(2u, fifth_pass_quad_list.size());
376
377     TestQuadMatchesExpectations(root_quads[2][0],
378                                 fifth_pass_quad_list.ElementAt(0));
379
380     // The last quad in the last pass will reference the second pass from the
381     // root surface, which after aggregating is the fourth pass in the overall
382     // list.
383     ASSERT_EQ(DrawQuad::RENDER_PASS,
384               fifth_pass_quad_list.ElementAt(1)->material);
385     const RenderPassDrawQuad* fifth_pass_render_pass_draw_quad =
386         RenderPassDrawQuad::MaterialCast(fifth_pass_quad_list.ElementAt(1));
387     EXPECT_EQ(actual_pass_ids[3],
388               fifth_pass_render_pass_draw_quad->render_pass_id);
389   }
390   factory_.Destroy(embedded_surface_id);
391 }
392
393 // Tests an invalid surface reference in a frame. The surface quad should just
394 // be dropped.
395 TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {
396   test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
397                         test::Quad::SurfaceQuad(InvalidSurfaceId()),
398                         test::Quad::SolidColorQuad(SK_ColorBLUE)};
399   test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
400
401   SubmitFrame(passes, arraysize(passes), root_surface_id_);
402
403   test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
404                                  test::Quad::SolidColorQuad(SK_ColorBLUE)};
405   test::Pass expected_passes[] = {
406       test::Pass(expected_quads, arraysize(expected_quads))};
407   SurfaceId ids[] = {root_surface_id_, InvalidSurfaceId()};
408   AggregateAndVerify(
409       expected_passes, arraysize(expected_passes), ids, arraysize(ids));
410 }
411
412 // Tests a reference to a valid surface with no submitted frame. This quad
413 // should also just be dropped.
414 TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) {
415   SurfaceId surface_with_no_frame_id = allocator_.GenerateId();
416   factory_.Create(surface_with_no_frame_id, gfx::Size(5, 5));
417   test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
418                         test::Quad::SurfaceQuad(surface_with_no_frame_id),
419                         test::Quad::SolidColorQuad(SK_ColorBLUE)};
420   test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
421
422   SubmitFrame(passes, arraysize(passes), root_surface_id_);
423
424   test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
425                                  test::Quad::SolidColorQuad(SK_ColorBLUE)};
426   test::Pass expected_passes[] = {
427       test::Pass(expected_quads, arraysize(expected_quads))};
428   SurfaceId ids[] = {root_surface_id_, surface_with_no_frame_id};
429   AggregateAndVerify(
430       expected_passes, arraysize(expected_passes), ids, arraysize(ids));
431   factory_.Destroy(surface_with_no_frame_id);
432 }
433
434 // Tests a surface quad referencing itself, generating a trivial cycle.
435 // The quad creating the cycle should be dropped from the final frame.
436 TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {
437   test::Quad quads[] = {test::Quad::SurfaceQuad(root_surface_id_),
438                         test::Quad::SolidColorQuad(SK_ColorYELLOW)};
439   test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
440
441   SubmitFrame(passes, arraysize(passes), root_surface_id_);
442
443   test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorYELLOW)};
444   test::Pass expected_passes[] = {
445       test::Pass(expected_quads, arraysize(expected_quads))};
446   SurfaceId ids[] = {root_surface_id_};
447   AggregateAndVerify(
448       expected_passes, arraysize(expected_passes), ids, arraysize(ids));
449 }
450
451 // Tests a more complex cycle with one intermediate surface.
452 TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
453   SurfaceId child_surface_id = allocator_.GenerateId();
454   factory_.Create(child_surface_id, SurfaceSize());
455
456   test::Quad parent_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
457                                test::Quad::SurfaceQuad(child_surface_id),
458                                test::Quad::SolidColorQuad(SK_ColorCYAN)};
459   test::Pass parent_passes[] = {
460       test::Pass(parent_quads, arraysize(parent_quads))};
461
462   SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
463
464   test::Quad child_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
465                               test::Quad::SurfaceQuad(root_surface_id_),
466                               test::Quad::SolidColorQuad(SK_ColorMAGENTA)};
467   test::Pass child_passes[] = {test::Pass(child_quads, arraysize(child_quads))};
468
469   SubmitFrame(child_passes, arraysize(child_passes), child_surface_id);
470
471   // The child surface's reference to the root_surface_ will be dropped, so
472   // we'll end up with:
473   //   SK_ColorBLUE from the parent
474   //   SK_ColorGREEN from the child
475   //   SK_ColorMAGENTA from the child
476   //   SK_ColorCYAN from the parent
477   test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
478                                  test::Quad::SolidColorQuad(SK_ColorGREEN),
479                                  test::Quad::SolidColorQuad(SK_ColorMAGENTA),
480                                  test::Quad::SolidColorQuad(SK_ColorCYAN)};
481   test::Pass expected_passes[] = {
482       test::Pass(expected_quads, arraysize(expected_quads))};
483   SurfaceId ids[] = {root_surface_id_, child_surface_id};
484   AggregateAndVerify(
485       expected_passes, arraysize(expected_passes), ids, arraysize(ids));
486   factory_.Destroy(child_surface_id);
487 }
488
489 // Tests that we map render pass IDs from different surfaces into a unified
490 // namespace and update RenderPassDrawQuad's id references to match.
491 TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
492   SurfaceId child_surface_id = allocator_.GenerateId();
493   factory_.Create(child_surface_id, SurfaceSize());
494
495   RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
496   test::Quad child_quad[][1] = {{test::Quad::SolidColorQuad(SK_ColorGREEN)},
497                                 {test::Quad::RenderPassQuad(child_pass_id[0])}};
498   test::Pass surface_passes[] = {
499       test::Pass(child_quad[0], arraysize(child_quad[0]), child_pass_id[0]),
500       test::Pass(child_quad[1], arraysize(child_quad[1]), child_pass_id[1])};
501
502   SubmitFrame(surface_passes, arraysize(surface_passes), child_surface_id);
503
504   // Pass IDs from the parent surface may collide with ones from the child.
505   RenderPassId parent_pass_id[] = {RenderPassId(2, 1), RenderPassId(1, 2)};
506   test::Quad parent_quad[][1] = {
507       {test::Quad::SurfaceQuad(child_surface_id)},
508       {test::Quad::RenderPassQuad(parent_pass_id[0])}};
509   test::Pass parent_passes[] = {
510       test::Pass(parent_quad[0], arraysize(parent_quad[0]), parent_pass_id[0]),
511       test::Pass(parent_quad[1], arraysize(parent_quad[1]), parent_pass_id[1])};
512
513   SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
514   scoped_ptr<CompositorFrame> aggregated_frame =
515       aggregator_.Aggregate(root_surface_id_);
516
517   ASSERT_TRUE(aggregated_frame);
518   ASSERT_TRUE(aggregated_frame->delegated_frame_data);
519
520   DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
521
522   const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
523
524   ASSERT_EQ(3u, aggregated_pass_list.size());
525   RenderPassId actual_pass_ids[] = {aggregated_pass_list[0]->id,
526                                     aggregated_pass_list[1]->id,
527                                     aggregated_pass_list[2]->id};
528   // Make sure the aggregated frame's pass IDs are all unique.
529   for (size_t i = 0; i < 3; ++i) {
530     for (size_t j = 0; j < i; ++j) {
531       EXPECT_NE(actual_pass_ids[j], actual_pass_ids[i]) << "pass ids " << i
532                                                         << " and " << j;
533     }
534   }
535
536   // Make sure the render pass quads reference the remapped pass IDs.
537   DrawQuad* render_pass_quads[] = {aggregated_pass_list[1]->quad_list.front(),
538                                    aggregated_pass_list[2]->quad_list.front()};
539   ASSERT_EQ(render_pass_quads[0]->material, DrawQuad::RENDER_PASS);
540   EXPECT_EQ(
541       actual_pass_ids[0],
542       RenderPassDrawQuad::MaterialCast(render_pass_quads[0])->render_pass_id);
543
544   ASSERT_EQ(render_pass_quads[1]->material, DrawQuad::RENDER_PASS);
545   EXPECT_EQ(
546       actual_pass_ids[1],
547       RenderPassDrawQuad::MaterialCast(render_pass_quads[1])->render_pass_id);
548   factory_.Destroy(child_surface_id);
549 }
550
551 void AddSolidColorQuadWithBlendMode(const gfx::Size& size,
552                                     RenderPass* pass,
553                                     const SkXfermode::Mode blend_mode) {
554   const gfx::Transform content_to_target_transform;
555   const gfx::Size content_bounds(size);
556   const gfx::Rect visible_content_rect(size);
557   const gfx::Rect clip_rect(size);
558
559   bool is_clipped = false;
560   float opacity = 1.f;
561
562   bool force_anti_aliasing_off = false;
563   SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
564   sqs->SetAll(content_to_target_transform,
565               content_bounds,
566               visible_content_rect,
567               clip_rect,
568               is_clipped,
569               opacity,
570               blend_mode,
571               0);
572
573   SolidColorDrawQuad* color_quad =
574       pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
575   color_quad->SetNew(pass->shared_quad_state_list.back(),
576                      visible_content_rect,
577                      visible_content_rect,
578                      SK_ColorGREEN,
579                      force_anti_aliasing_off);
580 }
581
582 // This tests that we update shared quad state pointers correctly within
583 // aggregated passes.  The shared quad state list on the aggregated pass will
584 // include the shared quad states from each pass in one list so the quads will
585 // end up pointed to shared quad state objects at different offsets. This test
586 // uses the blend_mode value stored on the shared quad state to track the shared
587 // quad state, but anything saved on the shared quad state would work.
588 //
589 // This test has 4 surfaces in the following structure:
590 // root_surface -> quad with kClear_Mode,
591 //                 [child_one_surface],
592 //                 quad with kDstOver_Mode,
593 //                 [child_two_surface],
594 //                 quad with kDstIn_Mode
595 // child_one_surface -> quad with kSrc_Mode,
596 //                      [grandchild_surface],
597 //                      quad with kSrcOver_Mode
598 // child_two_surface -> quad with kSrcIn_Mode
599 // grandchild_surface -> quad with kDst_Mode
600 //
601 // Resulting in the following aggregated pass:
602 //  quad_root_0       - blend_mode kClear_Mode
603 //  quad_child_one_0  - blend_mode kSrc_Mode
604 //  quad_grandchild_0 - blend_mode kDst_Mode
605 //  quad_child_one_1  - blend_mode kSrcOver_Mode
606 //  quad_root_1       - blend_mode kDstOver_Mode
607 //  quad_child_two_0  - blend_mode kSrcIn_Mode
608 //  quad_root_2       - blend_mode kDstIn_Mode
609 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
610   const SkXfermode::Mode blend_modes[] = {SkXfermode::kClear_Mode,    // 0
611                                           SkXfermode::kSrc_Mode,      // 1
612                                           SkXfermode::kDst_Mode,      // 2
613                                           SkXfermode::kSrcOver_Mode,  // 3
614                                           SkXfermode::kDstOver_Mode,  // 4
615                                           SkXfermode::kSrcIn_Mode,    // 5
616                                           SkXfermode::kDstIn_Mode,    // 6
617   };
618
619   RenderPassId pass_id(1, 1);
620   SurfaceId grandchild_surface_id = allocator_.GenerateId();
621   factory_.Create(grandchild_surface_id, SurfaceSize());
622   scoped_ptr<RenderPass> grandchild_pass = RenderPass::Create();
623   gfx::Rect output_rect(SurfaceSize());
624   gfx::Rect damage_rect(SurfaceSize());
625   gfx::Transform transform_to_root_target;
626   grandchild_pass->SetNew(
627       pass_id, output_rect, damage_rect, transform_to_root_target);
628   AddSolidColorQuadWithBlendMode(
629       SurfaceSize(), grandchild_pass.get(), blend_modes[2]);
630   QueuePassAsFrame(grandchild_pass.Pass(), grandchild_surface_id);
631
632   SurfaceId child_one_surface_id = allocator_.GenerateId();
633   factory_.Create(child_one_surface_id, SurfaceSize());
634
635   scoped_ptr<RenderPass> child_one_pass = RenderPass::Create();
636   child_one_pass->SetNew(
637       pass_id, output_rect, damage_rect, transform_to_root_target);
638   AddSolidColorQuadWithBlendMode(
639       SurfaceSize(), child_one_pass.get(), blend_modes[1]);
640   SurfaceDrawQuad* grandchild_surface_quad =
641       child_one_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
642   grandchild_surface_quad->SetNew(child_one_pass->shared_quad_state_list.back(),
643                                   gfx::Rect(SurfaceSize()),
644                                   gfx::Rect(SurfaceSize()),
645                                   grandchild_surface_id);
646   AddSolidColorQuadWithBlendMode(
647       SurfaceSize(), child_one_pass.get(), blend_modes[3]);
648   QueuePassAsFrame(child_one_pass.Pass(), child_one_surface_id);
649
650   SurfaceId child_two_surface_id = allocator_.GenerateId();
651   factory_.Create(child_two_surface_id, SurfaceSize());
652
653   scoped_ptr<RenderPass> child_two_pass = RenderPass::Create();
654   child_two_pass->SetNew(
655       pass_id, output_rect, damage_rect, transform_to_root_target);
656   AddSolidColorQuadWithBlendMode(
657       SurfaceSize(), child_two_pass.get(), blend_modes[5]);
658   QueuePassAsFrame(child_two_pass.Pass(), child_two_surface_id);
659
660   scoped_ptr<RenderPass> root_pass = RenderPass::Create();
661   root_pass->SetNew(
662       pass_id, output_rect, damage_rect, transform_to_root_target);
663
664   AddSolidColorQuadWithBlendMode(
665       SurfaceSize(), root_pass.get(), blend_modes[0]);
666   SurfaceDrawQuad* child_one_surface_quad =
667       root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
668   child_one_surface_quad->SetNew(root_pass->shared_quad_state_list.back(),
669                                  gfx::Rect(SurfaceSize()),
670                                  gfx::Rect(SurfaceSize()),
671                                  child_one_surface_id);
672   AddSolidColorQuadWithBlendMode(
673       SurfaceSize(), root_pass.get(), blend_modes[4]);
674   SurfaceDrawQuad* child_two_surface_quad =
675       root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
676   child_two_surface_quad->SetNew(root_pass->shared_quad_state_list.back(),
677                                  gfx::Rect(SurfaceSize()),
678                                  gfx::Rect(SurfaceSize()),
679                                  child_two_surface_id);
680   AddSolidColorQuadWithBlendMode(
681       SurfaceSize(), root_pass.get(), blend_modes[6]);
682
683   QueuePassAsFrame(root_pass.Pass(), root_surface_id_);
684
685   scoped_ptr<CompositorFrame> aggregated_frame =
686       aggregator_.Aggregate(root_surface_id_);
687
688   ASSERT_TRUE(aggregated_frame);
689   ASSERT_TRUE(aggregated_frame->delegated_frame_data);
690
691   DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
692
693   const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
694
695   ASSERT_EQ(1u, aggregated_pass_list.size());
696
697   const QuadList& aggregated_quad_list = aggregated_pass_list[0]->quad_list;
698
699   ASSERT_EQ(7u, aggregated_quad_list.size());
700
701   size_t i = 0;
702   for (QuadList::ConstIterator iter = aggregated_quad_list.begin();
703        iter != aggregated_quad_list.end();
704        ++iter) {
705     EXPECT_EQ(blend_modes[i], iter->shared_quad_state->blend_mode) << i;
706     ++i;
707   }
708   factory_.Destroy(child_one_surface_id);
709   factory_.Destroy(child_two_surface_id);
710   factory_.Destroy(grandchild_surface_id);
711 }
712
713 // This tests that when aggregating a frame with multiple render passes that we
714 // map the transforms for the root pass but do not modify the transform on child
715 // passes.
716 //
717 // The root surface has one pass with a surface quad transformed by +10 in the y
718 // direction.
719 //
720 // The child surface has two passes. The first pass has a quad with a transform
721 // of +5 in the x direction. The second pass has a reference to the first pass'
722 // pass id and a transform of +8 in the x direction.
723 //
724 // After aggregation, the child surface's root pass quad should have both
725 // transforms concatenated for a total transform of +8 x, +10 y. The
726 // contributing render pass' transform in the aggregate frame should not be
727 // affected.
728 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
729   SurfaceId child_surface_id = allocator_.GenerateId();
730   factory_.Create(child_surface_id, SurfaceSize());
731   RenderPassId child_pass_id[] = {RenderPassId(1, 1), RenderPassId(1, 2)};
732   test::Quad child_quads[][1] = {
733       {test::Quad::SolidColorQuad(SK_ColorGREEN)},
734       {test::Quad::RenderPassQuad(child_pass_id[0])}};
735   test::Pass child_passes[] = {
736       test::Pass(child_quads[0], arraysize(child_quads[0]), child_pass_id[0]),
737       test::Pass(child_quads[1], arraysize(child_quads[1]), child_pass_id[1])};
738
739   RenderPassList child_pass_list;
740   AddPasses(&child_pass_list,
741             gfx::Rect(SurfaceSize()),
742             child_passes,
743             arraysize(child_passes));
744
745   RenderPass* child_nonroot_pass = child_pass_list.at(0u);
746   child_nonroot_pass->transform_to_root_target.Translate(8, 0);
747   SharedQuadState* child_nonroot_pass_sqs =
748       child_nonroot_pass->shared_quad_state_list[0];
749   child_nonroot_pass_sqs->content_to_target_transform.Translate(5, 0);
750
751   RenderPass* child_root_pass = child_pass_list.at(1u);
752   SharedQuadState* child_root_pass_sqs =
753       child_root_pass->shared_quad_state_list[0];
754   child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
755   child_root_pass_sqs->is_clipped = true;
756   child_root_pass_sqs->clip_rect = gfx::Rect(0, 0, 5, 5);
757
758   scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
759   child_pass_list.swap(child_frame_data->render_pass_list);
760
761   scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
762   child_frame->delegated_frame_data = child_frame_data.Pass();
763
764   factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
765
766   test::Quad root_quads[] = {test::Quad::SolidColorQuad(1),
767                              test::Quad::SurfaceQuad(child_surface_id)};
768   test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
769
770   RenderPassList root_pass_list;
771   AddPasses(&root_pass_list,
772             gfx::Rect(SurfaceSize()),
773             root_passes,
774             arraysize(root_passes));
775
776   root_pass_list.at(0)
777       ->shared_quad_state_list[0]
778       ->content_to_target_transform.Translate(0, 7);
779   root_pass_list.at(0)
780       ->shared_quad_state_list[1]
781       ->content_to_target_transform.Translate(0, 10);
782
783   scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
784   root_pass_list.swap(root_frame_data->render_pass_list);
785
786   scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
787   root_frame->delegated_frame_data = root_frame_data.Pass();
788
789   factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
790
791   scoped_ptr<CompositorFrame> aggregated_frame =
792       aggregator_.Aggregate(root_surface_id_);
793
794   ASSERT_TRUE(aggregated_frame);
795   ASSERT_TRUE(aggregated_frame->delegated_frame_data);
796
797   DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
798
799   const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
800
801   ASSERT_EQ(2u, aggregated_pass_list.size());
802
803   ASSERT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
804
805   // The first pass should have one shared quad state for the one solid color
806   // quad.
807   EXPECT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size());
808   // The second (root) pass should have just two shared quad states. We'll
809   // verify the properties through the quads.
810   EXPECT_EQ(2u, aggregated_pass_list[1]->shared_quad_state_list.size());
811
812   SharedQuadState* aggregated_first_pass_sqs =
813       aggregated_pass_list[0]->shared_quad_state_list.front();
814
815   // The first pass's transform should be unaffected by the embedding and still
816   // be a translation by +5 in the x direction.
817   gfx::Transform expected_aggregated_first_pass_sqs_transform;
818   expected_aggregated_first_pass_sqs_transform.Translate(5, 0);
819   EXPECT_EQ(expected_aggregated_first_pass_sqs_transform.ToString(),
820             aggregated_first_pass_sqs->content_to_target_transform.ToString());
821
822   // The first pass's transform to the root target should include the aggregated
823   // transform.
824   gfx::Transform expected_first_pass_transform_to_root_target;
825   expected_first_pass_transform_to_root_target.Translate(8, 10);
826   EXPECT_EQ(expected_first_pass_transform_to_root_target.ToString(),
827             aggregated_pass_list[0]->transform_to_root_target.ToString());
828
829   ASSERT_EQ(2u, aggregated_pass_list[1]->quad_list.size());
830
831   gfx::Transform expected_root_pass_quad_transforms[2];
832   // The first quad in the root pass is the solid color quad from the original
833   // root surface. Its transform should be unaffected by the aggregation and
834   // still be +7 in the y direction.
835   expected_root_pass_quad_transforms[0].Translate(0, 7);
836   // The second quad in the root pass is aggregated from the child surface so
837   // its transform should be the combination of its original translation (0, 10)
838   // and the child surface draw quad's translation (8, 0).
839   expected_root_pass_quad_transforms[1].Translate(8, 10);
840
841   size_t i = 0;
842   for (QuadList::Iterator iter = aggregated_pass_list[1]->quad_list.begin();
843        iter != aggregated_pass_list[1]->quad_list.end();
844        ++iter) {
845     EXPECT_EQ(expected_root_pass_quad_transforms[i].ToString(),
846               iter->quadTransform().ToString())
847         << i;
848     i++;
849   }
850
851   EXPECT_EQ(true,
852             aggregated_pass_list[1]->shared_quad_state_list[1]->is_clipped);
853
854   // The second quad in the root pass is aggregated from the child, so its
855   // clip rect must be transformed by the child's translation.
856   EXPECT_EQ(
857       gfx::Rect(0, 10, 5, 5).ToString(),
858       aggregated_pass_list[1]->shared_quad_state_list[1]->clip_rect.ToString());
859
860   factory_.Destroy(child_surface_id);
861 }
862
863 // Tests that damage rects are aggregated correctly when surfaces change.
864 TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateDamageRect) {
865   SurfaceId child_surface_id = allocator_.GenerateId();
866   factory_.Create(child_surface_id, SurfaceSize());
867   RenderPassId child_pass_id = RenderPassId(1, 1);
868   test::Quad child_quads[] = {test::Quad::RenderPassQuad(child_pass_id)};
869   test::Pass child_passes[] = {
870       test::Pass(child_quads, arraysize(child_quads), child_pass_id)};
871
872   RenderPassList child_pass_list;
873   AddPasses(&child_pass_list,
874             gfx::Rect(SurfaceSize()),
875             child_passes,
876             arraysize(child_passes));
877
878   RenderPass* child_root_pass = child_pass_list.at(0u);
879   SharedQuadState* child_root_pass_sqs =
880       child_root_pass->shared_quad_state_list[0];
881   child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
882
883   scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
884   child_pass_list.swap(child_frame_data->render_pass_list);
885
886   scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
887   child_frame->delegated_frame_data = child_frame_data.Pass();
888
889   factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
890
891   test::Quad root_quads[] = {test::Quad::SurfaceQuad(child_surface_id)};
892   test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
893
894   RenderPassList root_pass_list;
895   AddPasses(&root_pass_list,
896             gfx::Rect(SurfaceSize()),
897             root_passes,
898             arraysize(root_passes));
899
900   root_pass_list.at(0)
901       ->shared_quad_state_list[0]
902       ->content_to_target_transform.Translate(0, 10);
903   root_pass_list.at(0)->damage_rect = gfx::Rect(5, 5, 10, 10);
904
905   scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
906   root_pass_list.swap(root_frame_data->render_pass_list);
907
908   scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
909   root_frame->delegated_frame_data = root_frame_data.Pass();
910
911   factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
912
913   scoped_ptr<CompositorFrame> aggregated_frame =
914       aggregator_.Aggregate(root_surface_id_);
915
916   ASSERT_TRUE(aggregated_frame);
917   ASSERT_TRUE(aggregated_frame->delegated_frame_data);
918
919   DelegatedFrameData* frame_data = aggregated_frame->delegated_frame_data.get();
920
921   const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
922
923   ASSERT_EQ(1u, aggregated_pass_list.size());
924
925   // Damage rect for first aggregation should contain entire root surface.
926   EXPECT_TRUE(
927       aggregated_pass_list[0]->damage_rect.Contains(gfx::Rect(SurfaceSize())));
928
929   {
930     AddPasses(&child_pass_list,
931               gfx::Rect(SurfaceSize()),
932               child_passes,
933               arraysize(child_passes));
934
935     RenderPass* child_root_pass = child_pass_list.at(0u);
936     SharedQuadState* child_root_pass_sqs =
937         child_root_pass->shared_quad_state_list[0];
938     child_root_pass_sqs->content_to_target_transform.Translate(8, 0);
939     child_root_pass->damage_rect = gfx::Rect(10, 10, 10, 10);
940
941     scoped_ptr<DelegatedFrameData> child_frame_data(new DelegatedFrameData);
942     child_pass_list.swap(child_frame_data->render_pass_list);
943
944     scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
945     child_frame->delegated_frame_data = child_frame_data.Pass();
946
947     factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure());
948
949     scoped_ptr<CompositorFrame> aggregated_frame =
950         aggregator_.Aggregate(root_surface_id_);
951
952     ASSERT_TRUE(aggregated_frame);
953     ASSERT_TRUE(aggregated_frame->delegated_frame_data);
954
955     DelegatedFrameData* frame_data =
956         aggregated_frame->delegated_frame_data.get();
957
958     const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
959
960     ASSERT_EQ(1u, aggregated_pass_list.size());
961
962     // Outer surface didn't change, so transformed inner damage rect should be
963     // used.
964     EXPECT_EQ(gfx::Rect(10, 20, 10, 10).ToString(),
965               aggregated_pass_list[0]->damage_rect.ToString());
966   }
967
968   {
969     RenderPassList root_pass_list;
970     AddPasses(&root_pass_list,
971               gfx::Rect(SurfaceSize()),
972               root_passes,
973               arraysize(root_passes));
974
975     root_pass_list.at(0)
976         ->shared_quad_state_list[0]
977         ->content_to_target_transform.Translate(0, 10);
978     root_pass_list.at(0)->damage_rect = gfx::Rect(0, 0, 1, 1);
979
980     scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
981     root_pass_list.swap(root_frame_data->render_pass_list);
982
983     scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
984     root_frame->delegated_frame_data = root_frame_data.Pass();
985
986     factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
987   }
988
989   {
990     RenderPassList root_pass_list;
991     AddPasses(&root_pass_list,
992               gfx::Rect(SurfaceSize()),
993               root_passes,
994               arraysize(root_passes));
995
996     root_pass_list.at(0)
997         ->shared_quad_state_list[0]
998         ->content_to_target_transform.Translate(0, 10);
999     root_pass_list.at(0)->damage_rect = gfx::Rect(1, 1, 1, 1);
1000
1001     scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData);
1002     root_pass_list.swap(root_frame_data->render_pass_list);
1003
1004     scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
1005     root_frame->delegated_frame_data = root_frame_data.Pass();
1006
1007     factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure());
1008
1009     scoped_ptr<CompositorFrame> aggregated_frame =
1010         aggregator_.Aggregate(root_surface_id_);
1011
1012     ASSERT_TRUE(aggregated_frame);
1013     ASSERT_TRUE(aggregated_frame->delegated_frame_data);
1014
1015     DelegatedFrameData* frame_data =
1016         aggregated_frame->delegated_frame_data.get();
1017
1018     const RenderPassList& aggregated_pass_list = frame_data->render_pass_list;
1019
1020     ASSERT_EQ(1u, aggregated_pass_list.size());
1021
1022     // The root surface was enqueued without being aggregated once, so it should
1023     // be treated as completely damaged.
1024     EXPECT_TRUE(aggregated_pass_list[0]->damage_rect.Contains(
1025         gfx::Rect(SurfaceSize())));
1026   }
1027
1028   factory_.Destroy(child_surface_id);
1029 }
1030
1031 class SurfaceAggregatorWithResourcesTest : public testing::Test {
1032  public:
1033   virtual void SetUp() {
1034     output_surface_ = FakeOutputSurface::CreateSoftware(
1035         make_scoped_ptr(new SoftwareOutputDevice));
1036     output_surface_->BindToClient(&output_surface_client_);
1037     shared_bitmap_manager_.reset(new TestSharedBitmapManager);
1038
1039     resource_provider_ = ResourceProvider::Create(output_surface_.get(),
1040                                                   shared_bitmap_manager_.get(),
1041                                                   NULL,
1042                                                   0,
1043                                                   false,
1044                                                   1,
1045                                                   false);
1046
1047     aggregator_.reset(
1048         new SurfaceAggregator(&manager_, resource_provider_.get()));
1049   }
1050
1051  protected:
1052   SurfaceManager manager_;
1053   FakeOutputSurfaceClient output_surface_client_;
1054   scoped_ptr<OutputSurface> output_surface_;
1055   scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
1056   scoped_ptr<ResourceProvider> resource_provider_;
1057   scoped_ptr<SurfaceAggregator> aggregator_;
1058 };
1059
1060 class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient {
1061  public:
1062   ResourceTrackingSurfaceFactoryClient() {}
1063   virtual ~ResourceTrackingSurfaceFactoryClient() {}
1064
1065   virtual void ReturnResources(
1066       const ReturnedResourceArray& resources) OVERRIDE {
1067     returned_resources_ = resources;
1068   }
1069
1070   ReturnedResourceArray returned_resources() const {
1071     return returned_resources_;
1072   }
1073
1074  private:
1075   ReturnedResourceArray returned_resources_;
1076
1077   DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient);
1078 };
1079
1080 void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids,
1081                               size_t num_resource_ids,
1082                               SurfaceFactory* factory,
1083                               SurfaceId surface_id) {
1084   scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
1085   scoped_ptr<RenderPass> pass = RenderPass::Create();
1086   pass->id = RenderPassId(1, 1);
1087   SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
1088   for (size_t i = 0u; i < num_resource_ids; ++i) {
1089     TransferableResource resource;
1090     resource.id = resource_ids[i];
1091     resource.is_software = true;
1092     frame_data->resource_list.push_back(resource);
1093     TextureDrawQuad* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
1094     const gfx::Rect rect;
1095     const gfx::Rect opaque_rect;
1096     const gfx::Rect visible_rect;
1097     bool needs_blending = false;
1098     bool premultiplied_alpha = false;
1099     const gfx::PointF uv_top_left;
1100     const gfx::PointF uv_bottom_right;
1101     SkColor background_color = SK_ColorGREEN;
1102     const float vertex_opacity[4] = {0.f, 0.f, 1.f, 1.f};
1103     bool flipped = false;
1104     quad->SetAll(sqs,
1105                  rect,
1106                  opaque_rect,
1107                  visible_rect,
1108                  needs_blending,
1109                  resource_ids[i],
1110                  premultiplied_alpha,
1111                  uv_top_left,
1112                  uv_bottom_right,
1113                  background_color,
1114                  vertex_opacity,
1115                  flipped);
1116
1117     quad->shared_quad_state = sqs;
1118   }
1119   frame_data->render_pass_list.push_back(pass.Pass());
1120   scoped_ptr<CompositorFrame> frame(new CompositorFrame);
1121   frame->delegated_frame_data = frame_data.Pass();
1122   factory->SubmitFrame(surface_id, frame.Pass(), base::Closure());
1123 }
1124
1125 TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
1126   ResourceTrackingSurfaceFactoryClient client;
1127   SurfaceFactory factory(&manager_, &client);
1128   SurfaceId surface_id(7u);
1129   factory.Create(surface_id, SurfaceSize());
1130
1131   ResourceProvider::ResourceId ids[] = {11, 12, 13};
1132   SubmitFrameWithResources(ids, arraysize(ids), &factory, surface_id);
1133
1134   scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id);
1135
1136   // Nothing should be available to be returned yet.
1137   EXPECT_TRUE(client.returned_resources().empty());
1138
1139   SubmitFrameWithResources(NULL, 0u, &factory, surface_id);
1140
1141   frame = aggregator_->Aggregate(surface_id);
1142
1143   ASSERT_EQ(3u, client.returned_resources().size());
1144   ResourceProvider::ResourceId returned_ids[3];
1145   for (size_t i = 0; i < 3; ++i) {
1146     returned_ids[i] = client.returned_resources()[i].id;
1147   }
1148   EXPECT_THAT(returned_ids,
1149               testing::WhenSorted(testing::ElementsAreArray(ids)));
1150   factory.Destroy(surface_id);
1151 }
1152
1153 }  // namespace
1154 }  // namespace cc
1155