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