Home | History | Annotate | Download | only in resources
      1 // Copyright 2012 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/resources/prioritized_resource.h"
      6 
      7 #include <vector>
      8 
      9 #include "cc/resources/prioritized_resource_manager.h"
     10 #include "cc/resources/resource.h"
     11 #include "cc/resources/resource_provider.h"
     12 #include "cc/test/fake_output_surface.h"
     13 #include "cc/test/fake_output_surface_client.h"
     14 #include "cc/test/fake_proxy.h"
     15 #include "cc/test/test_shared_bitmap_manager.h"
     16 #include "cc/test/tiled_layer_test_common.h"
     17 #include "cc/trees/single_thread_proxy.h"  // For DebugScopedSetImplThread
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 namespace cc {
     21 
     22 class PrioritizedResourceTest : public testing::Test {
     23  public:
     24   PrioritizedResourceTest()
     25       : texture_size_(256, 256),
     26         texture_format_(RGBA_8888),
     27         output_surface_(FakeOutputSurface::Create3d()) {
     28     DebugScopedSetImplThread impl_thread(&proxy_);
     29     CHECK(output_surface_->BindToClient(&output_surface_client_));
     30     shared_bitmap_manager_.reset(new TestSharedBitmapManager());
     31     resource_provider_ = ResourceProvider::Create(output_surface_.get(),
     32                                                   shared_bitmap_manager_.get(),
     33                                                   NULL,
     34                                                   0,
     35                                                   false,
     36                                                   1,
     37                                                   false);
     38   }
     39 
     40   virtual ~PrioritizedResourceTest() {
     41     DebugScopedSetImplThread impl_thread(&proxy_);
     42     resource_provider_.reset();
     43   }
     44 
     45   size_t TexturesMemorySize(size_t texture_count) {
     46     return Resource::MemorySizeBytes(texture_size_, texture_format_) *
     47            texture_count;
     48   }
     49 
     50   scoped_ptr<PrioritizedResourceManager> CreateManager(size_t max_textures) {
     51     scoped_ptr<PrioritizedResourceManager> manager =
     52         PrioritizedResourceManager::Create(&proxy_);
     53     manager->SetMaxMemoryLimitBytes(TexturesMemorySize(max_textures));
     54     return manager.Pass();
     55   }
     56 
     57   bool ValidateTexture(PrioritizedResource* texture,
     58                        bool request_late) {
     59     ResourceManagerAssertInvariants(texture->resource_manager());
     60     if (request_late)
     61       texture->RequestLate();
     62     ResourceManagerAssertInvariants(texture->resource_manager());
     63     DebugScopedSetImplThreadAndMainThreadBlocked
     64         impl_thread_and_main_thread_blocked(&proxy_);
     65     bool success = texture->can_acquire_backing_texture();
     66     if (success)
     67       texture->AcquireBackingTexture(resource_provider());
     68     return success;
     69   }
     70 
     71   void PrioritizeTexturesAndBackings(
     72       PrioritizedResourceManager* resource_manager) {
     73     resource_manager->PrioritizeTextures();
     74     ResourceManagerUpdateBackingsPriorities(resource_manager);
     75   }
     76 
     77   void ResourceManagerUpdateBackingsPriorities(
     78       PrioritizedResourceManager* resource_manager) {
     79     DebugScopedSetImplThreadAndMainThreadBlocked
     80         impl_thread_and_main_thread_blocked(&proxy_);
     81     resource_manager->PushTexturePrioritiesToBackings();
     82   }
     83 
     84   ResourceProvider* resource_provider() { return resource_provider_.get(); }
     85 
     86   void ResourceManagerAssertInvariants(
     87       PrioritizedResourceManager* resource_manager) {
     88     DebugScopedSetImplThreadAndMainThreadBlocked
     89         impl_thread_and_main_thread_blocked(&proxy_);
     90     resource_manager->AssertInvariants();
     91   }
     92 
     93   bool TextureBackingIsAbovePriorityCutoff(PrioritizedResource* texture) {
     94     return texture->backing()->
     95         was_above_priority_cutoff_at_last_priority_update();
     96   }
     97 
     98   size_t EvictedBackingCount(PrioritizedResourceManager* resource_manager) {
     99     return resource_manager->evicted_backings_.size();
    100   }
    101 
    102   std::vector<unsigned> BackingResources(
    103       PrioritizedResourceManager* resource_manager) {
    104     std::vector<unsigned> resources;
    105     for (PrioritizedResourceManager::BackingList::iterator it =
    106              resource_manager->backings_.begin();
    107          it != resource_manager->backings_.end();
    108          ++it)
    109       resources.push_back((*it)->id());
    110     return resources;
    111   }
    112 
    113  protected:
    114   FakeProxy proxy_;
    115   const gfx::Size texture_size_;
    116   const ResourceFormat texture_format_;
    117   FakeOutputSurfaceClient output_surface_client_;
    118   scoped_ptr<OutputSurface> output_surface_;
    119   scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
    120   scoped_ptr<ResourceProvider> resource_provider_;
    121 };
    122 
    123 namespace {
    124 
    125 TEST_F(PrioritizedResourceTest, RequestTextureExceedingMaxLimit) {
    126   const size_t kMaxTextures = 8;
    127   scoped_ptr<PrioritizedResourceManager> resource_manager =
    128       CreateManager(kMaxTextures);
    129 
    130   // Create textures for double our memory limit.
    131   scoped_ptr<PrioritizedResource> textures[kMaxTextures * 2];
    132 
    133   for (size_t i = 0; i < kMaxTextures * 2; ++i)
    134     textures[i] =
    135         resource_manager->CreateTexture(texture_size_, texture_format_);
    136 
    137   // Set decreasing priorities
    138   for (size_t i = 0; i < kMaxTextures * 2; ++i)
    139     textures[i]->set_request_priority(100 + i);
    140 
    141   // Only lower half should be available.
    142   PrioritizeTexturesAndBackings(resource_manager.get());
    143   EXPECT_TRUE(ValidateTexture(textures[0].get(), false));
    144   EXPECT_TRUE(ValidateTexture(textures[7].get(), false));
    145   EXPECT_FALSE(ValidateTexture(textures[8].get(), false));
    146   EXPECT_FALSE(ValidateTexture(textures[15].get(), false));
    147 
    148   // Set increasing priorities
    149   for (size_t i = 0; i < kMaxTextures * 2; ++i)
    150     textures[i]->set_request_priority(100 - i);
    151 
    152   // Only upper half should be available.
    153   PrioritizeTexturesAndBackings(resource_manager.get());
    154   EXPECT_FALSE(ValidateTexture(textures[0].get(), false));
    155   EXPECT_FALSE(ValidateTexture(textures[7].get(), false));
    156   EXPECT_TRUE(ValidateTexture(textures[8].get(), false));
    157   EXPECT_TRUE(ValidateTexture(textures[15].get(), false));
    158 
    159   EXPECT_EQ(TexturesMemorySize(kMaxTextures),
    160             resource_manager->MemoryAboveCutoffBytes());
    161   EXPECT_LE(resource_manager->MemoryUseBytes(),
    162             resource_manager->MemoryAboveCutoffBytes());
    163   EXPECT_EQ(TexturesMemorySize(2*kMaxTextures),
    164             resource_manager->MaxMemoryNeededBytes());
    165 
    166   DebugScopedSetImplThreadAndMainThreadBlocked
    167       impl_thread_and_main_thread_blocked(&proxy_);
    168   resource_manager->ClearAllMemory(resource_provider());
    169 }
    170 
    171 TEST_F(PrioritizedResourceTest, ChangeMemoryLimits) {
    172   const size_t kMaxTextures = 8;
    173   scoped_ptr<PrioritizedResourceManager> resource_manager =
    174       CreateManager(kMaxTextures);
    175   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
    176 
    177   for (size_t i = 0; i < kMaxTextures; ++i) {
    178     textures[i] =
    179         resource_manager->CreateTexture(texture_size_, texture_format_);
    180   }
    181   for (size_t i = 0; i < kMaxTextures; ++i)
    182     textures[i]->set_request_priority(100 + i);
    183 
    184   // Set max limit to 8 textures
    185   resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(8));
    186   PrioritizeTexturesAndBackings(resource_manager.get());
    187   for (size_t i = 0; i < kMaxTextures; ++i)
    188     ValidateTexture(textures[i].get(), false);
    189   {
    190     DebugScopedSetImplThreadAndMainThreadBlocked
    191         impl_thread_and_main_thread_blocked(&proxy_);
    192     resource_manager->ReduceMemory(resource_provider());
    193   }
    194 
    195   EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes());
    196   EXPECT_LE(resource_manager->MemoryUseBytes(),
    197             resource_manager->MemoryAboveCutoffBytes());
    198 
    199   // Set max limit to 5 textures
    200   resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(5));
    201   PrioritizeTexturesAndBackings(resource_manager.get());
    202   for (size_t i = 0; i < kMaxTextures; ++i)
    203     EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 5);
    204   {
    205     DebugScopedSetImplThreadAndMainThreadBlocked
    206         impl_thread_and_main_thread_blocked(&proxy_);
    207     resource_manager->ReduceMemory(resource_provider());
    208   }
    209 
    210   EXPECT_EQ(TexturesMemorySize(5), resource_manager->MemoryAboveCutoffBytes());
    211   EXPECT_LE(resource_manager->MemoryUseBytes(),
    212             resource_manager->MemoryAboveCutoffBytes());
    213   EXPECT_EQ(TexturesMemorySize(kMaxTextures),
    214             resource_manager->MaxMemoryNeededBytes());
    215 
    216   // Set max limit to 4 textures
    217   resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(4));
    218   PrioritizeTexturesAndBackings(resource_manager.get());
    219   for (size_t i = 0; i < kMaxTextures; ++i)
    220     EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4);
    221   {
    222     DebugScopedSetImplThreadAndMainThreadBlocked
    223         impl_thread_and_main_thread_blocked(&proxy_);
    224     resource_manager->ReduceMemory(resource_provider());
    225   }
    226 
    227   EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
    228   EXPECT_LE(resource_manager->MemoryUseBytes(),
    229             resource_manager->MemoryAboveCutoffBytes());
    230   EXPECT_EQ(TexturesMemorySize(kMaxTextures),
    231             resource_manager->MaxMemoryNeededBytes());
    232 
    233   DebugScopedSetImplThreadAndMainThreadBlocked
    234       impl_thread_and_main_thread_blocked(&proxy_);
    235   resource_manager->ClearAllMemory(resource_provider());
    236 }
    237 
    238 TEST_F(PrioritizedResourceTest, ReduceWastedMemory) {
    239   const size_t kMaxTextures = 20;
    240   scoped_ptr<PrioritizedResourceManager> resource_manager =
    241       CreateManager(kMaxTextures);
    242   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
    243 
    244   for (size_t i = 0; i < kMaxTextures; ++i) {
    245     textures[i] =
    246         resource_manager->CreateTexture(texture_size_, texture_format_);
    247   }
    248   for (size_t i = 0; i < kMaxTextures; ++i)
    249     textures[i]->set_request_priority(100 + i);
    250 
    251   // Set the memory limit to the max number of textures.
    252   resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures));
    253   PrioritizeTexturesAndBackings(resource_manager.get());
    254 
    255   // Create backings and textures for all of the textures.
    256   for (size_t i = 0; i < kMaxTextures; ++i) {
    257     ValidateTexture(textures[i].get(), false);
    258 
    259     {
    260       DebugScopedSetImplThreadAndMainThreadBlocked
    261           impl_thread_and_main_thread_blocked(&proxy_);
    262       uint8_t image[4] = {0};
    263       textures[i]->SetPixels(resource_provider_.get(),
    264                              image,
    265                              gfx::Rect(1, 1),
    266                              gfx::Rect(1, 1),
    267                              gfx::Vector2d());
    268     }
    269   }
    270   {
    271     DebugScopedSetImplThreadAndMainThreadBlocked
    272         impl_thread_and_main_thread_blocked(&proxy_);
    273     resource_manager->ReduceMemory(resource_provider());
    274   }
    275 
    276   // 20 textures have backings allocated.
    277   EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
    278 
    279   // Destroy one texture, not enough is wasted to cause cleanup.
    280   textures[0] = scoped_ptr<PrioritizedResource>();
    281   PrioritizeTexturesAndBackings(resource_manager.get());
    282   {
    283     DebugScopedSetImplThreadAndMainThreadBlocked
    284         impl_thread_and_main_thread_blocked(&proxy_);
    285     resource_manager->UpdateBackingsState(resource_provider());
    286     resource_manager->ReduceWastedMemory(resource_provider());
    287   }
    288   EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
    289 
    290   // Destroy half the textures, leaving behind the backings. Now a cleanup
    291   // should happen.
    292   for (size_t i = 0; i < kMaxTextures / 2; ++i)
    293     textures[i] = scoped_ptr<PrioritizedResource>();
    294   PrioritizeTexturesAndBackings(resource_manager.get());
    295   {
    296     DebugScopedSetImplThreadAndMainThreadBlocked
    297         impl_thread_and_main_thread_blocked(&proxy_);
    298     resource_manager->UpdateBackingsState(resource_provider());
    299     resource_manager->ReduceWastedMemory(resource_provider());
    300   }
    301   EXPECT_GT(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
    302 
    303   DebugScopedSetImplThreadAndMainThreadBlocked
    304       impl_thread_and_main_thread_blocked(&proxy_);
    305   resource_manager->ClearAllMemory(resource_provider());
    306 }
    307 
    308 TEST_F(PrioritizedResourceTest, InUseNotWastedMemory) {
    309   const size_t kMaxTextures = 20;
    310   scoped_ptr<PrioritizedResourceManager> resource_manager =
    311       CreateManager(kMaxTextures);
    312   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
    313 
    314   for (size_t i = 0; i < kMaxTextures; ++i) {
    315     textures[i] =
    316         resource_manager->CreateTexture(texture_size_, texture_format_);
    317   }
    318   for (size_t i = 0; i < kMaxTextures; ++i)
    319     textures[i]->set_request_priority(100 + i);
    320 
    321   // Set the memory limit to the max number of textures.
    322   resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures));
    323   PrioritizeTexturesAndBackings(resource_manager.get());
    324 
    325   // Create backings and textures for all of the textures.
    326   for (size_t i = 0; i < kMaxTextures; ++i) {
    327     ValidateTexture(textures[i].get(), false);
    328 
    329     {
    330       DebugScopedSetImplThreadAndMainThreadBlocked
    331           impl_thread_and_main_thread_blocked(&proxy_);
    332       uint8_t image[4] = {0};
    333       textures[i]->SetPixels(resource_provider_.get(),
    334                              image,
    335                              gfx::Rect(1, 1),
    336                              gfx::Rect(1, 1),
    337                              gfx::Vector2d());
    338     }
    339   }
    340   {
    341     DebugScopedSetImplThreadAndMainThreadBlocked
    342         impl_thread_and_main_thread_blocked(&proxy_);
    343     resource_manager->ReduceMemory(resource_provider());
    344   }
    345 
    346   // 20 textures have backings allocated.
    347   EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
    348 
    349   // Send half the textures to a parent compositor.
    350   ResourceProvider::ResourceIdArray to_send;
    351   TransferableResourceArray transferable;
    352   for (size_t i = 0; i < kMaxTextures / 2; ++i)
    353     to_send.push_back(textures[i]->resource_id());
    354   resource_provider_->PrepareSendToParent(to_send, &transferable);
    355 
    356   // Destroy half the textures, leaving behind the backings. The backings are
    357   // sent to a parent compositor though, so they should not be considered wasted
    358   // and a cleanup should not happen.
    359   for (size_t i = 0; i < kMaxTextures / 2; ++i)
    360     textures[i] = scoped_ptr<PrioritizedResource>();
    361   PrioritizeTexturesAndBackings(resource_manager.get());
    362   {
    363     DebugScopedSetImplThreadAndMainThreadBlocked
    364         impl_thread_and_main_thread_blocked(&proxy_);
    365     resource_manager->UpdateBackingsState(resource_provider());
    366     resource_manager->ReduceWastedMemory(resource_provider());
    367   }
    368   EXPECT_EQ(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
    369 
    370   // Receive the textures back from the parent compositor. Now a cleanup should
    371   // happen.
    372   ReturnedResourceArray returns;
    373   TransferableResource::ReturnResources(transferable, &returns);
    374   resource_provider_->ReceiveReturnsFromParent(returns);
    375   {
    376     DebugScopedSetImplThreadAndMainThreadBlocked
    377         impl_thread_and_main_thread_blocked(&proxy_);
    378     resource_manager->UpdateBackingsState(resource_provider());
    379     resource_manager->ReduceWastedMemory(resource_provider());
    380   }
    381   EXPECT_GT(TexturesMemorySize(20), resource_manager->MemoryUseBytes());
    382 
    383   DebugScopedSetImplThreadAndMainThreadBlocked
    384       impl_thread_and_main_thread_blocked(&proxy_);
    385   resource_manager->ClearAllMemory(resource_provider());
    386 }
    387 
    388 TEST_F(PrioritizedResourceTest, ChangePriorityCutoff) {
    389   const size_t kMaxTextures = 8;
    390   scoped_ptr<PrioritizedResourceManager> resource_manager =
    391       CreateManager(kMaxTextures);
    392   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
    393 
    394   for (size_t i = 0; i < kMaxTextures; ++i) {
    395     textures[i] =
    396         resource_manager->CreateTexture(texture_size_, texture_format_);
    397   }
    398   for (size_t i = 0; i < kMaxTextures; ++i)
    399     textures[i]->set_request_priority(100 + i);
    400 
    401   // Set the cutoff to drop two textures. Try to request_late on all textures,
    402   // and make sure that request_late doesn't work on a texture with equal
    403   // priority to the cutoff.
    404   resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(8));
    405   resource_manager->SetExternalPriorityCutoff(106);
    406   PrioritizeTexturesAndBackings(resource_manager.get());
    407   for (size_t i = 0; i < kMaxTextures; ++i)
    408     EXPECT_EQ(ValidateTexture(textures[i].get(), true), i < 6);
    409   {
    410     DebugScopedSetImplThreadAndMainThreadBlocked
    411         impl_thread_and_main_thread_blocked(&proxy_);
    412     resource_manager->ReduceMemory(resource_provider());
    413   }
    414   EXPECT_EQ(TexturesMemorySize(6), resource_manager->MemoryAboveCutoffBytes());
    415   EXPECT_LE(resource_manager->MemoryUseBytes(),
    416             resource_manager->MemoryAboveCutoffBytes());
    417 
    418   // Set the cutoff to drop two more textures.
    419   resource_manager->SetExternalPriorityCutoff(104);
    420   PrioritizeTexturesAndBackings(resource_manager.get());
    421   for (size_t i = 0; i < kMaxTextures; ++i)
    422     EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4);
    423   {
    424     DebugScopedSetImplThreadAndMainThreadBlocked
    425         impl_thread_and_main_thread_blocked(&proxy_);
    426     resource_manager->ReduceMemory(resource_provider());
    427   }
    428   EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
    429 
    430   // Do a one-time eviction for one more texture based on priority cutoff
    431   resource_manager->UnlinkAndClearEvictedBackings();
    432   {
    433     DebugScopedSetImplThreadAndMainThreadBlocked
    434         impl_thread_and_main_thread_blocked(&proxy_);
    435     resource_manager->ReduceMemoryOnImplThread(
    436         TexturesMemorySize(8), 104, resource_provider());
    437     EXPECT_EQ(0u, EvictedBackingCount(resource_manager.get()));
    438     resource_manager->ReduceMemoryOnImplThread(
    439         TexturesMemorySize(8), 103, resource_provider());
    440     EXPECT_EQ(1u, EvictedBackingCount(resource_manager.get()));
    441   }
    442   resource_manager->UnlinkAndClearEvictedBackings();
    443   EXPECT_EQ(TexturesMemorySize(3), resource_manager->MemoryUseBytes());
    444 
    445   // Re-allocate the the texture after the one-time drop.
    446   PrioritizeTexturesAndBackings(resource_manager.get());
    447   for (size_t i = 0; i < kMaxTextures; ++i)
    448     EXPECT_EQ(ValidateTexture(textures[i].get(), false), i < 4);
    449   {
    450     DebugScopedSetImplThreadAndMainThreadBlocked
    451         impl_thread_and_main_thread_blocked(&proxy_);
    452     resource_manager->ReduceMemory(resource_provider());
    453   }
    454   EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
    455 
    456   DebugScopedSetImplThreadAndMainThreadBlocked
    457       impl_thread_and_main_thread_blocked(&proxy_);
    458   resource_manager->ClearAllMemory(resource_provider());
    459 }
    460 
    461 TEST_F(PrioritizedResourceTest, EvictingTexturesInParent) {
    462   const size_t kMaxTextures = 8;
    463   scoped_ptr<PrioritizedResourceManager> resource_manager =
    464       CreateManager(kMaxTextures);
    465   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
    466   unsigned texture_resource_ids[kMaxTextures];
    467 
    468   for (size_t i = 0; i < kMaxTextures; ++i) {
    469     textures[i] =
    470         resource_manager->CreateTexture(texture_size_, texture_format_);
    471     textures[i]->set_request_priority(100 + i);
    472   }
    473 
    474   PrioritizeTexturesAndBackings(resource_manager.get());
    475   for (size_t i = 0; i < kMaxTextures; ++i) {
    476     EXPECT_TRUE(ValidateTexture(textures[i].get(), true));
    477 
    478     {
    479       DebugScopedSetImplThreadAndMainThreadBlocked
    480           impl_thread_and_main_thread_blocked(&proxy_);
    481       uint8_t image[4] = {0};
    482       textures[i]->SetPixels(resource_provider_.get(),
    483                              image,
    484                              gfx::Rect(1, 1),
    485                              gfx::Rect(1, 1),
    486                              gfx::Vector2d());
    487     }
    488   }
    489   {
    490     DebugScopedSetImplThreadAndMainThreadBlocked
    491         impl_thread_and_main_thread_blocked(&proxy_);
    492     resource_manager->ReduceMemory(resource_provider());
    493   }
    494   EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes());
    495 
    496   for (size_t i = 0; i < 8; ++i)
    497     texture_resource_ids[i] = textures[i]->resource_id();
    498 
    499   // Evict four textures. It will be the last four.
    500   {
    501     DebugScopedSetImplThreadAndMainThreadBlocked
    502         impl_thread_and_main_thread_blocked(&proxy_);
    503     resource_manager->ReduceMemoryOnImplThread(
    504         TexturesMemorySize(4), 200, resource_provider());
    505 
    506     EXPECT_EQ(4u, EvictedBackingCount(resource_manager.get()));
    507 
    508     // The last four backings are evicted.
    509     std::vector<unsigned> remaining = BackingResources(resource_manager.get());
    510     EXPECT_TRUE(std::find(remaining.begin(),
    511                           remaining.end(),
    512                           texture_resource_ids[0]) != remaining.end());
    513     EXPECT_TRUE(std::find(remaining.begin(),
    514                           remaining.end(),
    515                           texture_resource_ids[1]) != remaining.end());
    516     EXPECT_TRUE(std::find(remaining.begin(),
    517                           remaining.end(),
    518                           texture_resource_ids[2]) != remaining.end());
    519     EXPECT_TRUE(std::find(remaining.begin(),
    520                           remaining.end(),
    521                           texture_resource_ids[3]) != remaining.end());
    522   }
    523   resource_manager->UnlinkAndClearEvictedBackings();
    524   EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryUseBytes());
    525 
    526   // Re-allocate the the texture after the eviction.
    527   PrioritizeTexturesAndBackings(resource_manager.get());
    528   for (size_t i = 0; i < kMaxTextures; ++i) {
    529     EXPECT_TRUE(ValidateTexture(textures[i].get(), true));
    530 
    531     {
    532       DebugScopedSetImplThreadAndMainThreadBlocked
    533           impl_thread_and_main_thread_blocked(&proxy_);
    534       uint8_t image[4] = {0};
    535       textures[i]->SetPixels(resource_provider_.get(),
    536                              image,
    537                              gfx::Rect(1, 1),
    538                              gfx::Rect(1, 1),
    539                              gfx::Vector2d());
    540     }
    541   }
    542   {
    543     DebugScopedSetImplThreadAndMainThreadBlocked
    544         impl_thread_and_main_thread_blocked(&proxy_);
    545     resource_manager->ReduceMemory(resource_provider());
    546   }
    547   EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes());
    548 
    549   // Send the last two of the textures to a parent compositor.
    550   ResourceProvider::ResourceIdArray to_send;
    551   TransferableResourceArray transferable;
    552   for (size_t i = 6; i < 8; ++i)
    553     to_send.push_back(textures[i]->resource_id());
    554   resource_provider_->PrepareSendToParent(to_send, &transferable);
    555 
    556   // Set the last two textures to be tied for prioity with the two
    557   // before them. Being sent to the parent will break the tie.
    558   textures[4]->set_request_priority(100 + 4);
    559   textures[5]->set_request_priority(100 + 5);
    560   textures[6]->set_request_priority(100 + 4);
    561   textures[7]->set_request_priority(100 + 5);
    562 
    563   for (size_t i = 0; i < 8; ++i)
    564     texture_resource_ids[i] = textures[i]->resource_id();
    565 
    566   // Drop all the textures. Now we have backings that can be recycled.
    567   for (size_t i = 0; i < 8; ++i)
    568     textures[0].reset();
    569   PrioritizeTexturesAndBackings(resource_manager.get());
    570 
    571   // The next commit finishes.
    572   {
    573     DebugScopedSetImplThreadAndMainThreadBlocked
    574         impl_thread_and_main_thread_blocked(&proxy_);
    575     resource_manager->UpdateBackingsState(resource_provider());
    576   }
    577 
    578   // Evict four textures. It would be the last four again, except that 2 of them
    579   // are sent to the parent, so they are evicted last.
    580   {
    581     DebugScopedSetImplThreadAndMainThreadBlocked
    582         impl_thread_and_main_thread_blocked(&proxy_);
    583     resource_manager->ReduceMemoryOnImplThread(
    584         TexturesMemorySize(4), 200, resource_provider());
    585 
    586     EXPECT_EQ(4u, EvictedBackingCount(resource_manager.get()));
    587     // The last 2 backings remain this time.
    588     std::vector<unsigned> remaining = BackingResources(resource_manager.get());
    589     EXPECT_TRUE(std::find(remaining.begin(),
    590                           remaining.end(),
    591                           texture_resource_ids[6]) == remaining.end());
    592     EXPECT_TRUE(std::find(remaining.begin(),
    593                           remaining.end(),
    594                           texture_resource_ids[7]) == remaining.end());
    595   }
    596   resource_manager->UnlinkAndClearEvictedBackings();
    597   EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryUseBytes());
    598 
    599   DebugScopedSetImplThreadAndMainThreadBlocked
    600       impl_thread_and_main_thread_blocked(&proxy_);
    601   resource_manager->ClearAllMemory(resource_provider());
    602 }
    603 
    604 TEST_F(PrioritizedResourceTest, ResourceManagerPartialUpdateTextures) {
    605   const size_t kMaxTextures = 4;
    606   const size_t kNumTextures = 4;
    607   scoped_ptr<PrioritizedResourceManager> resource_manager =
    608       CreateManager(kMaxTextures);
    609   scoped_ptr<PrioritizedResource> textures[kNumTextures];
    610   scoped_ptr<PrioritizedResource> more_textures[kNumTextures];
    611 
    612   for (size_t i = 0; i < kNumTextures; ++i) {
    613     textures[i] =
    614         resource_manager->CreateTexture(texture_size_, texture_format_);
    615     more_textures[i] =
    616         resource_manager->CreateTexture(texture_size_, texture_format_);
    617   }
    618 
    619   for (size_t i = 0; i < kNumTextures; ++i)
    620     textures[i]->set_request_priority(200 + i);
    621   PrioritizeTexturesAndBackings(resource_manager.get());
    622 
    623   // Allocate textures which are currently high priority.
    624   EXPECT_TRUE(ValidateTexture(textures[0].get(), false));
    625   EXPECT_TRUE(ValidateTexture(textures[1].get(), false));
    626   EXPECT_TRUE(ValidateTexture(textures[2].get(), false));
    627   EXPECT_TRUE(ValidateTexture(textures[3].get(), false));
    628 
    629   EXPECT_TRUE(textures[0]->have_backing_texture());
    630   EXPECT_TRUE(textures[1]->have_backing_texture());
    631   EXPECT_TRUE(textures[2]->have_backing_texture());
    632   EXPECT_TRUE(textures[3]->have_backing_texture());
    633 
    634   for (size_t i = 0; i < kNumTextures; ++i)
    635     more_textures[i]->set_request_priority(100 + i);
    636   PrioritizeTexturesAndBackings(resource_manager.get());
    637 
    638   // Textures are now below cutoff.
    639   EXPECT_FALSE(ValidateTexture(textures[0].get(), false));
    640   EXPECT_FALSE(ValidateTexture(textures[1].get(), false));
    641   EXPECT_FALSE(ValidateTexture(textures[2].get(), false));
    642   EXPECT_FALSE(ValidateTexture(textures[3].get(), false));
    643 
    644   // But they are still valid to use.
    645   EXPECT_TRUE(textures[0]->have_backing_texture());
    646   EXPECT_TRUE(textures[1]->have_backing_texture());
    647   EXPECT_TRUE(textures[2]->have_backing_texture());
    648   EXPECT_TRUE(textures[3]->have_backing_texture());
    649 
    650   // Higher priority textures are finally needed.
    651   EXPECT_TRUE(ValidateTexture(more_textures[0].get(), false));
    652   EXPECT_TRUE(ValidateTexture(more_textures[1].get(), false));
    653   EXPECT_TRUE(ValidateTexture(more_textures[2].get(), false));
    654   EXPECT_TRUE(ValidateTexture(more_textures[3].get(), false));
    655 
    656   // Lower priority have been fully evicted.
    657   EXPECT_FALSE(textures[0]->have_backing_texture());
    658   EXPECT_FALSE(textures[1]->have_backing_texture());
    659   EXPECT_FALSE(textures[2]->have_backing_texture());
    660   EXPECT_FALSE(textures[3]->have_backing_texture());
    661 
    662   DebugScopedSetImplThreadAndMainThreadBlocked
    663       impl_thread_and_main_thread_blocked(&proxy_);
    664   resource_manager->ClearAllMemory(resource_provider());
    665 }
    666 
    667 TEST_F(PrioritizedResourceTest, ResourceManagerPrioritiesAreEqual) {
    668   const size_t kMaxTextures = 16;
    669   scoped_ptr<PrioritizedResourceManager> resource_manager =
    670       CreateManager(kMaxTextures);
    671   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
    672 
    673   for (size_t i = 0; i < kMaxTextures; ++i) {
    674     textures[i] =
    675         resource_manager->CreateTexture(texture_size_, texture_format_);
    676   }
    677 
    678   // All 16 textures have the same priority except 2 higher priority.
    679   for (size_t i = 0; i < kMaxTextures; ++i)
    680     textures[i]->set_request_priority(100);
    681   textures[0]->set_request_priority(99);
    682   textures[1]->set_request_priority(99);
    683 
    684   // Set max limit to 8 textures
    685   resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(8));
    686   PrioritizeTexturesAndBackings(resource_manager.get());
    687 
    688   // The two high priority textures should be available, others should not.
    689   for (size_t i = 0; i < 2; ++i)
    690     EXPECT_TRUE(ValidateTexture(textures[i].get(), false));
    691   for (size_t i = 2; i < kMaxTextures; ++i)
    692     EXPECT_FALSE(ValidateTexture(textures[i].get(), false));
    693   EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryAboveCutoffBytes());
    694   EXPECT_LE(resource_manager->MemoryUseBytes(),
    695             resource_manager->MemoryAboveCutoffBytes());
    696 
    697   // Manually reserving textures should only succeed on the higher priority
    698   // textures, and on remaining textures up to the memory limit.
    699   for (size_t i = 0; i < 8; i++)
    700     EXPECT_TRUE(ValidateTexture(textures[i].get(), true));
    701   for (size_t i = 9; i < kMaxTextures; i++)
    702     EXPECT_FALSE(ValidateTexture(textures[i].get(), true));
    703   EXPECT_EQ(TexturesMemorySize(8), resource_manager->MemoryAboveCutoffBytes());
    704   EXPECT_LE(resource_manager->MemoryUseBytes(),
    705             resource_manager->MemoryAboveCutoffBytes());
    706 
    707   DebugScopedSetImplThreadAndMainThreadBlocked
    708       impl_thread_and_main_thread_blocked(&proxy_);
    709   resource_manager->ClearAllMemory(resource_provider());
    710 }
    711 
    712 TEST_F(PrioritizedResourceTest, ResourceManagerDestroyedFirst) {
    713   scoped_ptr<PrioritizedResourceManager> resource_manager = CreateManager(1);
    714   scoped_ptr<PrioritizedResource> texture =
    715       resource_manager->CreateTexture(texture_size_, texture_format_);
    716 
    717   // Texture is initially invalid, but it will become available.
    718   EXPECT_FALSE(texture->have_backing_texture());
    719 
    720   texture->set_request_priority(100);
    721   PrioritizeTexturesAndBackings(resource_manager.get());
    722 
    723   EXPECT_TRUE(ValidateTexture(texture.get(), false));
    724   EXPECT_TRUE(texture->can_acquire_backing_texture());
    725   EXPECT_TRUE(texture->have_backing_texture());
    726   {
    727     DebugScopedSetImplThreadAndMainThreadBlocked
    728         impl_thread_and_main_thread_blocked(&proxy_);
    729     resource_manager->ClearAllMemory(resource_provider());
    730   }
    731   resource_manager.reset();
    732 
    733   EXPECT_FALSE(texture->can_acquire_backing_texture());
    734   EXPECT_FALSE(texture->have_backing_texture());
    735 }
    736 
    737 TEST_F(PrioritizedResourceTest, TextureMovedToNewManager) {
    738   scoped_ptr<PrioritizedResourceManager> resource_manager_one =
    739       CreateManager(1);
    740   scoped_ptr<PrioritizedResourceManager> resource_manager_two =
    741       CreateManager(1);
    742   scoped_ptr<PrioritizedResource> texture =
    743       resource_manager_one->CreateTexture(texture_size_, texture_format_);
    744 
    745   // Texture is initially invalid, but it will become available.
    746   EXPECT_FALSE(texture->have_backing_texture());
    747 
    748   texture->set_request_priority(100);
    749   PrioritizeTexturesAndBackings(resource_manager_one.get());
    750 
    751   EXPECT_TRUE(ValidateTexture(texture.get(), false));
    752   EXPECT_TRUE(texture->can_acquire_backing_texture());
    753   EXPECT_TRUE(texture->have_backing_texture());
    754 
    755   texture->SetTextureManager(NULL);
    756   {
    757     DebugScopedSetImplThreadAndMainThreadBlocked
    758         impl_thread_and_main_thread_blocked(&proxy_);
    759     resource_manager_one->ClearAllMemory(resource_provider());
    760   }
    761   resource_manager_one.reset();
    762 
    763   EXPECT_FALSE(texture->can_acquire_backing_texture());
    764   EXPECT_FALSE(texture->have_backing_texture());
    765 
    766   texture->SetTextureManager(resource_manager_two.get());
    767 
    768   PrioritizeTexturesAndBackings(resource_manager_two.get());
    769 
    770   EXPECT_TRUE(ValidateTexture(texture.get(), false));
    771   EXPECT_TRUE(texture->can_acquire_backing_texture());
    772   EXPECT_TRUE(texture->have_backing_texture());
    773 
    774   DebugScopedSetImplThreadAndMainThreadBlocked
    775       impl_thread_and_main_thread_blocked(&proxy_);
    776   resource_manager_two->ClearAllMemory(resource_provider());
    777 }
    778 
    779 TEST_F(PrioritizedResourceTest,
    780        RenderSurfacesReduceMemoryAvailableOutsideRootSurface) {
    781   const size_t kMaxTextures = 8;
    782   scoped_ptr<PrioritizedResourceManager> resource_manager =
    783       CreateManager(kMaxTextures);
    784 
    785   // Half of the memory is taken by surfaces (with high priority place-holder)
    786   scoped_ptr<PrioritizedResource> render_surface_place_holder =
    787       resource_manager->CreateTexture(texture_size_, texture_format_);
    788   render_surface_place_holder->SetToSelfManagedMemoryPlaceholder(
    789       TexturesMemorySize(4));
    790   render_surface_place_holder->set_request_priority(
    791       PriorityCalculator::RenderSurfacePriority());
    792 
    793   // Create textures to fill our memory limit.
    794   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
    795 
    796   for (size_t i = 0; i < kMaxTextures; ++i) {
    797     textures[i] =
    798         resource_manager->CreateTexture(texture_size_, texture_format_);
    799   }
    800 
    801   // Set decreasing non-visible priorities outside root surface.
    802   for (size_t i = 0; i < kMaxTextures; ++i)
    803     textures[i]->set_request_priority(100 + i);
    804 
    805   // Only lower half should be available.
    806   PrioritizeTexturesAndBackings(resource_manager.get());
    807   EXPECT_TRUE(ValidateTexture(textures[0].get(), false));
    808   EXPECT_TRUE(ValidateTexture(textures[3].get(), false));
    809   EXPECT_FALSE(ValidateTexture(textures[4].get(), false));
    810   EXPECT_FALSE(ValidateTexture(textures[7].get(), false));
    811 
    812   // Set increasing non-visible priorities outside root surface.
    813   for (size_t i = 0; i < kMaxTextures; ++i)
    814     textures[i]->set_request_priority(100 - i);
    815 
    816   // Only upper half should be available.
    817   PrioritizeTexturesAndBackings(resource_manager.get());
    818   EXPECT_FALSE(ValidateTexture(textures[0].get(), false));
    819   EXPECT_FALSE(ValidateTexture(textures[3].get(), false));
    820   EXPECT_TRUE(ValidateTexture(textures[4].get(), false));
    821   EXPECT_TRUE(ValidateTexture(textures[7].get(), false));
    822 
    823   EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
    824   EXPECT_EQ(TexturesMemorySize(4),
    825             resource_manager->MemoryForSelfManagedTextures());
    826   EXPECT_LE(resource_manager->MemoryUseBytes(),
    827             resource_manager->MemoryAboveCutoffBytes());
    828   EXPECT_EQ(TexturesMemorySize(8),
    829             resource_manager->MaxMemoryNeededBytes());
    830 
    831   DebugScopedSetImplThreadAndMainThreadBlocked
    832       impl_thread_and_main_thread_blocked(&proxy_);
    833   resource_manager->ClearAllMemory(resource_provider());
    834 }
    835 
    836 TEST_F(PrioritizedResourceTest,
    837        RenderSurfacesReduceMemoryAvailableForRequestLate) {
    838   const size_t kMaxTextures = 8;
    839   scoped_ptr<PrioritizedResourceManager> resource_manager =
    840       CreateManager(kMaxTextures);
    841 
    842   // Half of the memory is taken by surfaces (with high priority place-holder)
    843   scoped_ptr<PrioritizedResource> render_surface_place_holder =
    844       resource_manager->CreateTexture(texture_size_, texture_format_);
    845   render_surface_place_holder->SetToSelfManagedMemoryPlaceholder(
    846       TexturesMemorySize(4));
    847   render_surface_place_holder->set_request_priority(
    848       PriorityCalculator::RenderSurfacePriority());
    849 
    850   // Create textures to fill our memory limit.
    851   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
    852 
    853   for (size_t i = 0; i < kMaxTextures; ++i) {
    854     textures[i] =
    855         resource_manager->CreateTexture(texture_size_, texture_format_);
    856   }
    857 
    858   // Set equal priorities.
    859   for (size_t i = 0; i < kMaxTextures; ++i)
    860     textures[i]->set_request_priority(100);
    861 
    862   // The first four to be requested late will be available.
    863   PrioritizeTexturesAndBackings(resource_manager.get());
    864   for (unsigned i = 0; i < kMaxTextures; ++i)
    865     EXPECT_FALSE(ValidateTexture(textures[i].get(), false));
    866   for (unsigned i = 0; i < kMaxTextures; i += 2)
    867     EXPECT_TRUE(ValidateTexture(textures[i].get(), true));
    868   for (unsigned i = 1; i < kMaxTextures; i += 2)
    869     EXPECT_FALSE(ValidateTexture(textures[i].get(), true));
    870 
    871   EXPECT_EQ(TexturesMemorySize(4), resource_manager->MemoryAboveCutoffBytes());
    872   EXPECT_EQ(TexturesMemorySize(4),
    873             resource_manager->MemoryForSelfManagedTextures());
    874   EXPECT_LE(resource_manager->MemoryUseBytes(),
    875             resource_manager->MemoryAboveCutoffBytes());
    876   EXPECT_EQ(TexturesMemorySize(8),
    877             resource_manager->MaxMemoryNeededBytes());
    878 
    879   DebugScopedSetImplThreadAndMainThreadBlocked
    880       impl_thread_and_main_thread_blocked(&proxy_);
    881   resource_manager->ClearAllMemory(resource_provider());
    882 }
    883 
    884 TEST_F(PrioritizedResourceTest,
    885        WhenRenderSurfaceNotAvailableTexturesAlsoNotAvailable) {
    886   const size_t kMaxTextures = 8;
    887   scoped_ptr<PrioritizedResourceManager> resource_manager =
    888       CreateManager(kMaxTextures);
    889 
    890   // Half of the memory is taken by surfaces (with high priority place-holder)
    891   scoped_ptr<PrioritizedResource> render_surface_place_holder =
    892       resource_manager->CreateTexture(texture_size_, texture_format_);
    893   render_surface_place_holder->SetToSelfManagedMemoryPlaceholder(
    894       TexturesMemorySize(4));
    895   render_surface_place_holder->set_request_priority(
    896       PriorityCalculator::RenderSurfacePriority());
    897 
    898   // Create textures to fill our memory limit.
    899   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
    900 
    901   for (size_t i = 0; i < kMaxTextures; ++i)
    902     textures[i] =
    903         resource_manager->CreateTexture(texture_size_, texture_format_);
    904 
    905   // Set 6 visible textures in the root surface, and 2 in a child surface.
    906   for (size_t i = 0; i < 6; ++i) {
    907     textures[i]->
    908         set_request_priority(PriorityCalculator::VisiblePriority(true));
    909   }
    910   for (size_t i = 6; i < 8; ++i) {
    911     textures[i]->
    912         set_request_priority(PriorityCalculator::VisiblePriority(false));
    913   }
    914 
    915   PrioritizeTexturesAndBackings(resource_manager.get());
    916 
    917   // Unable to request_late textures in the child surface.
    918   EXPECT_FALSE(ValidateTexture(textures[6].get(), true));
    919   EXPECT_FALSE(ValidateTexture(textures[7].get(), true));
    920 
    921   // Root surface textures are valid.
    922   for (size_t i = 0; i < 6; ++i)
    923     EXPECT_TRUE(ValidateTexture(textures[i].get(), false));
    924 
    925   EXPECT_EQ(TexturesMemorySize(6), resource_manager->MemoryAboveCutoffBytes());
    926   EXPECT_EQ(TexturesMemorySize(2),
    927             resource_manager->MemoryForSelfManagedTextures());
    928   EXPECT_LE(resource_manager->MemoryUseBytes(),
    929             resource_manager->MemoryAboveCutoffBytes());
    930 
    931   DebugScopedSetImplThreadAndMainThreadBlocked
    932       impl_thread_and_main_thread_blocked(&proxy_);
    933   resource_manager->ClearAllMemory(resource_provider());
    934 }
    935 
    936 TEST_F(PrioritizedResourceTest, RequestLateBackingsSorting) {
    937   const size_t kMaxTextures = 8;
    938   scoped_ptr<PrioritizedResourceManager> resource_manager =
    939       CreateManager(kMaxTextures);
    940   resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures));
    941 
    942   // Create textures to fill our memory limit.
    943   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
    944   for (size_t i = 0; i < kMaxTextures; ++i)
    945     textures[i] =
    946         resource_manager->CreateTexture(texture_size_, texture_format_);
    947 
    948   // Set equal priorities, and allocate backings for all textures.
    949   for (size_t i = 0; i < kMaxTextures; ++i)
    950     textures[i]->set_request_priority(100);
    951   PrioritizeTexturesAndBackings(resource_manager.get());
    952   for (unsigned i = 0; i < kMaxTextures; ++i)
    953     EXPECT_TRUE(ValidateTexture(textures[i].get(), false));
    954 
    955   // Drop the memory limit and prioritize (none will be above the threshold,
    956   // but they still have backings because ReduceMemory hasn't been called).
    957   resource_manager->SetMaxMemoryLimitBytes(
    958       TexturesMemorySize(kMaxTextures / 2));
    959   PrioritizeTexturesAndBackings(resource_manager.get());
    960 
    961   // Push half of them back over the limit.
    962   for (size_t i = 0; i < kMaxTextures; i += 2)
    963     EXPECT_TRUE(textures[i]->RequestLate());
    964 
    965   // Push the priorities to the backings array and sort the backings array
    966   ResourceManagerUpdateBackingsPriorities(resource_manager.get());
    967 
    968   // Assert that the backings list be sorted with the below-limit backings
    969   // before the above-limit backings.
    970   ResourceManagerAssertInvariants(resource_manager.get());
    971 
    972   // Make sure that we have backings for all of the textures.
    973   for (size_t i = 0; i < kMaxTextures; ++i)
    974     EXPECT_TRUE(textures[i]->have_backing_texture());
    975 
    976   // Make sure that only the request_late textures are above the priority
    977   // cutoff
    978   for (size_t i = 0; i < kMaxTextures; i += 2)
    979     EXPECT_TRUE(TextureBackingIsAbovePriorityCutoff(textures[i].get()));
    980   for (size_t i = 1; i < kMaxTextures; i += 2)
    981     EXPECT_FALSE(TextureBackingIsAbovePriorityCutoff(textures[i].get()));
    982 
    983   DebugScopedSetImplThreadAndMainThreadBlocked
    984       impl_thread_and_main_thread_blocked(&proxy_);
    985   resource_manager->ClearAllMemory(resource_provider());
    986 }
    987 
    988 TEST_F(PrioritizedResourceTest, ClearUploadsToEvictedResources) {
    989   const size_t kMaxTextures = 4;
    990   scoped_ptr<PrioritizedResourceManager> resource_manager =
    991       CreateManager(kMaxTextures);
    992   resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(kMaxTextures));
    993 
    994   // Create textures to fill our memory limit.
    995   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
    996 
    997   for (size_t i = 0; i < kMaxTextures; ++i)
    998     textures[i] =
    999         resource_manager->CreateTexture(texture_size_, texture_format_);
   1000 
   1001   // Set equal priorities, and allocate backings for all textures.
   1002   for (size_t i = 0; i < kMaxTextures; ++i)
   1003     textures[i]->set_request_priority(100);
   1004   PrioritizeTexturesAndBackings(resource_manager.get());
   1005   for (unsigned i = 0; i < kMaxTextures; ++i)
   1006     EXPECT_TRUE(ValidateTexture(textures[i].get(), false));
   1007 
   1008   ResourceUpdateQueue queue;
   1009   DebugScopedSetImplThreadAndMainThreadBlocked
   1010       impl_thread_and_main_thread_blocked(&proxy_);
   1011   for (size_t i = 0; i < kMaxTextures; ++i) {
   1012     const ResourceUpdate upload = ResourceUpdate::Create(
   1013         textures[i].get(), NULL, gfx::Rect(), gfx::Rect(), gfx::Vector2d());
   1014     queue.AppendFullUpload(upload);
   1015   }
   1016 
   1017   // Make sure that we have backings for all of the textures.
   1018   for (size_t i = 0; i < kMaxTextures; ++i)
   1019     EXPECT_TRUE(textures[i]->have_backing_texture());
   1020 
   1021   queue.ClearUploadsToEvictedResources();
   1022   EXPECT_EQ(4u, queue.FullUploadSize());
   1023 
   1024   resource_manager->ReduceMemoryOnImplThread(
   1025       TexturesMemorySize(1),
   1026       PriorityCalculator::AllowEverythingCutoff(),
   1027       resource_provider());
   1028   queue.ClearUploadsToEvictedResources();
   1029   EXPECT_EQ(1u, queue.FullUploadSize());
   1030 
   1031   resource_manager->ReduceMemoryOnImplThread(
   1032       0, PriorityCalculator::AllowEverythingCutoff(), resource_provider());
   1033   queue.ClearUploadsToEvictedResources();
   1034   EXPECT_EQ(0u, queue.FullUploadSize());
   1035 }
   1036 
   1037 TEST_F(PrioritizedResourceTest, UsageStatistics) {
   1038   const size_t kMaxTextures = 5;
   1039   scoped_ptr<PrioritizedResourceManager> resource_manager =
   1040       CreateManager(kMaxTextures);
   1041   scoped_ptr<PrioritizedResource> textures[kMaxTextures];
   1042 
   1043   for (size_t i = 0; i < kMaxTextures; ++i) {
   1044     textures[i] =
   1045         resource_manager->CreateTexture(texture_size_, texture_format_);
   1046   }
   1047 
   1048   textures[0]->
   1049       set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
   1050   textures[1]->
   1051       set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff());
   1052   textures[2]->set_request_priority(
   1053       PriorityCalculator::AllowVisibleAndNearbyCutoff() - 1);
   1054   textures[3]->
   1055       set_request_priority(PriorityCalculator::AllowVisibleAndNearbyCutoff());
   1056   textures[4]->set_request_priority(
   1057       PriorityCalculator::AllowVisibleAndNearbyCutoff() + 1);
   1058 
   1059   // Set max limit to 2 textures.
   1060   resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(2));
   1061   PrioritizeTexturesAndBackings(resource_manager.get());
   1062 
   1063   // The first two textures should be available, others should not.
   1064   for (size_t i = 0; i < 2; ++i)
   1065     EXPECT_TRUE(ValidateTexture(textures[i].get(), false));
   1066   for (size_t i = 2; i < kMaxTextures; ++i)
   1067     EXPECT_FALSE(ValidateTexture(textures[i].get(), false));
   1068 
   1069   // Validate the statistics.
   1070   {
   1071     DebugScopedSetImplThread impl_thread(&proxy_);
   1072     EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes());
   1073     EXPECT_EQ(TexturesMemorySize(1), resource_manager->MemoryVisibleBytes());
   1074     EXPECT_EQ(TexturesMemorySize(3),
   1075               resource_manager->MemoryVisibleAndNearbyBytes());
   1076   }
   1077 
   1078   // Re-prioritize the textures, but do not push the values to backings.
   1079   textures[0]->
   1080       set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
   1081   textures[1]->
   1082       set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
   1083   textures[2]->
   1084       set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
   1085   textures[3]->set_request_priority(
   1086       PriorityCalculator::AllowVisibleAndNearbyCutoff() - 1);
   1087   textures[4]->
   1088       set_request_priority(PriorityCalculator::AllowVisibleAndNearbyCutoff());
   1089   resource_manager->PrioritizeTextures();
   1090 
   1091   // Verify that we still see the old values.
   1092   {
   1093     DebugScopedSetImplThread impl_thread(&proxy_);
   1094     EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes());
   1095     EXPECT_EQ(TexturesMemorySize(1), resource_manager->MemoryVisibleBytes());
   1096     EXPECT_EQ(TexturesMemorySize(3),
   1097               resource_manager->MemoryVisibleAndNearbyBytes());
   1098   }
   1099 
   1100   // Push priorities to backings, and verify we see the new values.
   1101   {
   1102     DebugScopedSetImplThreadAndMainThreadBlocked
   1103         impl_thread_and_main_thread_blocked(&proxy_);
   1104     resource_manager->PushTexturePrioritiesToBackings();
   1105     EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes());
   1106     EXPECT_EQ(TexturesMemorySize(3), resource_manager->MemoryVisibleBytes());
   1107     EXPECT_EQ(TexturesMemorySize(4),
   1108               resource_manager->MemoryVisibleAndNearbyBytes());
   1109   }
   1110 
   1111   DebugScopedSetImplThreadAndMainThreadBlocked
   1112       impl_thread_and_main_thread_blocked(&proxy_);
   1113   resource_manager->ClearAllMemory(resource_provider());
   1114 }
   1115 
   1116 }  // namespace
   1117 }  // namespace cc
   1118