Home | History | Annotate | Download | only in layers
      1 // Copyright 2013 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/layers/delegated_frame_provider.h"
      6 #include "cc/layers/delegated_frame_resource_collection.h"
      7 #include "cc/layers/delegated_renderer_layer.h"
      8 #include "cc/output/delegated_frame_data.h"
      9 #include "cc/quads/texture_draw_quad.h"
     10 #include "cc/resources/returned_resource.h"
     11 #include "cc/resources/transferable_resource.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 
     14 namespace cc {
     15 namespace {
     16 
     17 class DelegatedFrameProviderTest
     18     : public testing::Test,
     19       public DelegatedFrameResourceCollectionClient {
     20  protected:
     21   DelegatedFrameProviderTest() : resources_available_(false) {}
     22 
     23   scoped_ptr<DelegatedFrameData> CreateFrameData(
     24           const gfx::Rect& root_output_rect,
     25           const gfx::Rect& root_damage_rect) {
     26     scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData);
     27 
     28     scoped_ptr<RenderPass> root_pass(RenderPass::Create());
     29     root_pass->SetNew(RenderPass::Id(1, 1),
     30                       root_output_rect,
     31                       root_damage_rect,
     32                       gfx::Transform());
     33     frame->render_pass_list.push_back(root_pass.Pass());
     34     return frame.Pass();
     35   }
     36 
     37   void AddTransferableResource(DelegatedFrameData* frame,
     38                                ResourceProvider::ResourceId resource_id) {
     39     TransferableResource resource;
     40     resource.id = resource_id;
     41     resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
     42     frame->resource_list.push_back(resource);
     43   }
     44 
     45   void AddTextureQuad(DelegatedFrameData* frame,
     46                       ResourceProvider::ResourceId resource_id) {
     47     SharedQuadState* sqs =
     48         frame->render_pass_list[0]->CreateAndAppendSharedQuadState();
     49     scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
     50     float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f};
     51     quad->SetNew(sqs,
     52                  gfx::Rect(0, 0, 10, 10),
     53                  gfx::Rect(0, 0, 10, 10),
     54                  gfx::Rect(0, 0, 10, 10),
     55                  resource_id,
     56                  false,
     57                  gfx::PointF(0.f, 0.f),
     58                  gfx::PointF(1.f, 1.f),
     59                  SK_ColorTRANSPARENT,
     60                  vertex_opacity,
     61                  false);
     62     frame->render_pass_list[0]->quad_list.push_back(quad.PassAs<DrawQuad>());
     63   }
     64 
     65   virtual void SetUp() OVERRIDE {
     66     resource_collection_ = new DelegatedFrameResourceCollection;
     67     resource_collection_->SetClient(this);
     68   }
     69 
     70   virtual void TearDown() OVERRIDE { resource_collection_->SetClient(NULL); }
     71 
     72   virtual void UnusedResourcesAreAvailable() OVERRIDE {
     73     resources_available_ = true;
     74     resource_collection_->TakeUnusedResourcesForChildCompositor(&resources_);
     75   }
     76 
     77   bool ReturnAndResetResourcesAvailable() {
     78     bool r = resources_available_;
     79     resources_available_ = false;
     80     return r;
     81   }
     82 
     83   void SetFrameProvider(scoped_ptr<DelegatedFrameData> frame_data) {
     84     frame_provider_ =
     85         new DelegatedFrameProvider(resource_collection_, frame_data.Pass());
     86   }
     87 
     88   scoped_refptr<DelegatedFrameResourceCollection> resource_collection_;
     89   scoped_refptr<DelegatedFrameProvider> frame_provider_;
     90   bool resources_available_;
     91   ReturnedResourceArray resources_;
     92 };
     93 
     94 TEST_F(DelegatedFrameProviderTest, SameResources) {
     95   scoped_ptr<DelegatedFrameData> frame =
     96       CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
     97   AddTextureQuad(frame.get(), 444);
     98   AddTransferableResource(frame.get(), 444);
     99   SetFrameProvider(frame.Pass());
    100 
    101   frame = CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
    102   AddTextureQuad(frame.get(), 444);
    103   AddTransferableResource(frame.get(), 444);
    104   SetFrameProvider(frame.Pass());
    105 
    106   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    107   EXPECT_EQ(0u, resources_.size());
    108 
    109   frame_provider_ = NULL;
    110 
    111   EXPECT_TRUE(ReturnAndResetResourcesAvailable());
    112   EXPECT_EQ(1u, resources_.size());
    113   EXPECT_EQ(444u, resources_[0].id);
    114 }
    115 
    116 TEST_F(DelegatedFrameProviderTest, ReplaceResources) {
    117   scoped_ptr<DelegatedFrameData> frame =
    118       CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
    119   AddTextureQuad(frame.get(), 444);
    120   AddTransferableResource(frame.get(), 444);
    121   SetFrameProvider(frame.Pass());
    122 
    123   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    124 
    125   frame = CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
    126   AddTextureQuad(frame.get(), 555);
    127   AddTransferableResource(frame.get(), 555);
    128   SetFrameProvider(frame.Pass());
    129 
    130   EXPECT_TRUE(ReturnAndResetResourcesAvailable());
    131   EXPECT_EQ(1u, resources_.size());
    132   EXPECT_EQ(444u, resources_[0].id);
    133   resources_.clear();
    134 
    135   frame_provider_ = NULL;
    136 
    137   EXPECT_TRUE(ReturnAndResetResourcesAvailable());
    138   EXPECT_EQ(1u, resources_.size());
    139   EXPECT_EQ(555u, resources_[0].id);
    140 }
    141 
    142 TEST_F(DelegatedFrameProviderTest, RefResources) {
    143   scoped_ptr<DelegatedFrameData> frame =
    144       CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
    145   AddTextureQuad(frame.get(), 444);
    146   AddTransferableResource(frame.get(), 444);
    147 
    148   TransferableResourceArray reffed = frame->resource_list;
    149   ReturnedResourceArray returned;
    150   TransferableResource::ReturnResources(reffed, &returned);
    151 
    152   SetFrameProvider(frame.Pass());
    153 
    154   scoped_refptr<DelegatedRendererLayer> observer1 =
    155       DelegatedRendererLayer::Create(frame_provider_);
    156   scoped_refptr<DelegatedRendererLayer> observer2 =
    157       DelegatedRendererLayer::Create(frame_provider_);
    158 
    159   gfx::RectF damage;
    160 
    161   // Both observers get a full frame of damage on the first request.
    162   frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
    163   EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
    164   frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
    165   EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
    166 
    167   // And both get no damage on the 2nd request. This adds a second ref to the
    168   // resources.
    169   frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
    170   EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
    171   frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
    172   EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
    173 
    174   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    175 
    176   frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
    177   AddTextureQuad(frame.get(), 555);
    178   AddTransferableResource(frame.get(), 555);
    179   frame_provider_->SetFrameData(frame.Pass());
    180 
    181   // The resources from the first frame are still reffed by the observers.
    182   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    183 
    184   // There are 4 refs taken.
    185   frame_provider_->UnrefResourcesOnMainThread(returned);
    186   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    187   frame_provider_->UnrefResourcesOnMainThread(returned);
    188   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    189   frame_provider_->UnrefResourcesOnMainThread(returned);
    190   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    191 
    192   // The 4th unref will release them.
    193   frame_provider_->UnrefResourcesOnMainThread(returned);
    194 
    195   EXPECT_TRUE(ReturnAndResetResourcesAvailable());
    196   EXPECT_EQ(1u, resources_.size());
    197   EXPECT_EQ(444u, resources_[0].id);
    198 }
    199 
    200 TEST_F(DelegatedFrameProviderTest, RefResourcesInFrameProvider) {
    201   scoped_ptr<DelegatedFrameData> frame =
    202       CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
    203   AddTextureQuad(frame.get(), 444);
    204   AddTransferableResource(frame.get(), 444);
    205 
    206   TransferableResourceArray reffed = frame->resource_list;
    207   ReturnedResourceArray returned;
    208   TransferableResource::ReturnResources(reffed, &returned);
    209 
    210   SetFrameProvider(frame.Pass());
    211 
    212   scoped_refptr<DelegatedRendererLayer> observer1 =
    213       DelegatedRendererLayer::Create(frame_provider_);
    214   scoped_refptr<DelegatedRendererLayer> observer2 =
    215       DelegatedRendererLayer::Create(frame_provider_);
    216 
    217   gfx::RectF damage;
    218 
    219   // Take a ref on each observer.
    220   frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
    221   frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
    222 
    223   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    224 
    225   // Release both refs. But there's still a ref held in the frame
    226   // provider itself.
    227   frame_provider_->UnrefResourcesOnMainThread(returned);
    228   frame_provider_->UnrefResourcesOnMainThread(returned);
    229   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    230 
    231   // Setting a new frame will release it.
    232   frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
    233   AddTextureQuad(frame.get(), 555);
    234   AddTransferableResource(frame.get(), 555);
    235   frame_provider_->SetFrameData(frame.Pass());
    236 
    237   EXPECT_TRUE(ReturnAndResetResourcesAvailable());
    238   EXPECT_EQ(1u, resources_.size());
    239   EXPECT_EQ(444u, resources_[0].id);
    240 }
    241 
    242 TEST_F(DelegatedFrameProviderTest, RefResourcesInFrameProviderUntilDestroy) {
    243   scoped_ptr<DelegatedFrameData> frame =
    244       CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
    245   AddTextureQuad(frame.get(), 444);
    246   AddTransferableResource(frame.get(), 444);
    247 
    248   TransferableResourceArray reffed = frame->resource_list;
    249   ReturnedResourceArray returned;
    250   TransferableResource::ReturnResources(reffed, &returned);
    251 
    252   SetFrameProvider(frame.Pass());
    253 
    254   scoped_refptr<DelegatedRendererLayer> observer1 =
    255       DelegatedRendererLayer::Create(frame_provider_);
    256   scoped_refptr<DelegatedRendererLayer> observer2 =
    257       DelegatedRendererLayer::Create(frame_provider_);
    258 
    259   gfx::RectF damage;
    260 
    261   // Take a ref on each observer.
    262   frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
    263   frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
    264 
    265   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    266 
    267   // Release both refs. But there's still a ref held in the frame
    268   // provider itself.
    269   frame_provider_->UnrefResourcesOnMainThread(returned);
    270   frame_provider_->UnrefResourcesOnMainThread(returned);
    271   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    272 
    273   // Releasing all references to the frame provider will release
    274   // the frame.
    275   observer1 = NULL;
    276   observer2 = NULL;
    277   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    278 
    279   frame_provider_ = NULL;
    280 
    281   EXPECT_TRUE(ReturnAndResetResourcesAvailable());
    282   EXPECT_EQ(1u, resources_.size());
    283   EXPECT_EQ(444u, resources_[0].id);
    284 }
    285 
    286 TEST_F(DelegatedFrameProviderTest, Damage) {
    287   scoped_ptr<DelegatedFrameData> frame =
    288       CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
    289   AddTextureQuad(frame.get(), 444);
    290   AddTransferableResource(frame.get(), 444);
    291 
    292   TransferableResourceArray reffed = frame->resource_list;
    293   ReturnedResourceArray returned;
    294   TransferableResource::ReturnResources(reffed, &returned);
    295 
    296   SetFrameProvider(frame.Pass());
    297 
    298   scoped_refptr<DelegatedRendererLayer> observer1 =
    299       DelegatedRendererLayer::Create(frame_provider_);
    300   scoped_refptr<DelegatedRendererLayer> observer2 =
    301       DelegatedRendererLayer::Create(frame_provider_);
    302 
    303   gfx::RectF damage;
    304 
    305   // Both observers get a full frame of damage on the first request.
    306   frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
    307   EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
    308   frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
    309   EXPECT_EQ(gfx::RectF(5.f, 5.f).ToString(), damage.ToString());
    310 
    311   // And both get no damage on the 2nd request.
    312   frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
    313   EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
    314   frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
    315   EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
    316 
    317   frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(2, 2));
    318   AddTextureQuad(frame.get(), 555);
    319   AddTransferableResource(frame.get(), 555);
    320   frame_provider_->SetFrameData(frame.Pass());
    321 
    322   // Both observers get the damage for the new frame.
    323   frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
    324   EXPECT_EQ(gfx::RectF(2.f, 2.f).ToString(), damage.ToString());
    325   frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
    326   EXPECT_EQ(gfx::RectF(2.f, 2.f).ToString(), damage.ToString());
    327 
    328   // And both get no damage on the 2nd request.
    329   frame_provider_->GetFrameDataAndRefResources(observer1, &damage);
    330   EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
    331   frame_provider_->GetFrameDataAndRefResources(observer2, &damage);
    332   EXPECT_EQ(gfx::RectF().ToString(), damage.ToString());
    333 }
    334 
    335 TEST_F(DelegatedFrameProviderTest, LostNothing) {
    336   scoped_ptr<DelegatedFrameData> frame =
    337       CreateFrameData(gfx::Rect(5, 5), gfx::Rect(5, 5));
    338 
    339   TransferableResourceArray reffed = frame->resource_list;
    340 
    341   SetFrameProvider(frame.Pass());
    342 
    343   // There is nothing to lose.
    344   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    345   EXPECT_FALSE(resource_collection_->LoseAllResources());
    346   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    347   EXPECT_EQ(0u, resources_.size());
    348 }
    349 
    350 TEST_F(DelegatedFrameProviderTest, LostSomething) {
    351   scoped_ptr<DelegatedFrameData> frame =
    352       CreateFrameData(gfx::Rect(5, 5), gfx::Rect(5, 5));
    353   AddTextureQuad(frame.get(), 444);
    354   AddTransferableResource(frame.get(), 444);
    355 
    356   SetFrameProvider(frame.Pass());
    357 
    358   // Add a second reference on the resource.
    359   frame = CreateFrameData(gfx::Rect(5, 5), gfx::Rect(5, 5));
    360   AddTextureQuad(frame.get(), 444);
    361   AddTransferableResource(frame.get(), 444);
    362 
    363   SetFrameProvider(frame.Pass());
    364 
    365   // There is something to lose.
    366   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    367   EXPECT_TRUE(resource_collection_->LoseAllResources());
    368   EXPECT_TRUE(ReturnAndResetResourcesAvailable());
    369 
    370   EXPECT_EQ(1u, resources_.size());
    371   EXPECT_EQ(444u, resources_[0].id);
    372   EXPECT_EQ(2, resources_[0].count);
    373 }
    374 
    375 TEST_F(DelegatedFrameProviderTest, NothingReturnedAfterLoss) {
    376   scoped_ptr<DelegatedFrameData> frame =
    377       CreateFrameData(gfx::Rect(1, 1), gfx::Rect(1, 1));
    378   AddTextureQuad(frame.get(), 444);
    379   AddTransferableResource(frame.get(), 444);
    380   SetFrameProvider(frame.Pass());
    381 
    382   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    383 
    384   // Lose all the resources.
    385   EXPECT_TRUE(resource_collection_->LoseAllResources());
    386   EXPECT_TRUE(ReturnAndResetResourcesAvailable());
    387   resources_.clear();
    388 
    389   frame_provider_ = NULL;
    390 
    391   // Nothing is returned twice.
    392   EXPECT_FALSE(ReturnAndResetResourcesAvailable());
    393   EXPECT_EQ(0u, resources_.size());
    394 }
    395 
    396 }  // namespace
    397 }  // namespace cc
    398