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