Home | History | Annotate | Download | only in surfaces
      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 
   1156