• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
PrioritizedResourceTest()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 
~PrioritizedResourceTest()33   virtual ~PrioritizedResourceTest() {
34     DebugScopedSetImplThread impl_thread(&proxy_);
35     resource_provider_.reset();
36   }
37 
TexturesMemorySize(size_t texture_count)38   size_t TexturesMemorySize(size_t texture_count) {
39     return Resource::MemorySizeBytes(texture_size_, texture_format_) *
40            texture_count;
41   }
42 
CreateManager(size_t max_textures)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 
ValidateTexture(PrioritizedResource * texture,bool request_late)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 
PrioritizeTexturesAndBackings(PrioritizedResourceManager * resource_manager)64   void PrioritizeTexturesAndBackings(
65       PrioritizedResourceManager* resource_manager) {
66     resource_manager->PrioritizeTextures();
67     ResourceManagerUpdateBackingsPriorities(resource_manager);
68   }
69 
ResourceManagerUpdateBackingsPriorities(PrioritizedResourceManager * resource_manager)70   void ResourceManagerUpdateBackingsPriorities(
71       PrioritizedResourceManager* resource_manager) {
72     DebugScopedSetImplThreadAndMainThreadBlocked
73         impl_thread_and_main_thread_blocked(&proxy_);
74     resource_manager->PushTexturePrioritiesToBackings();
75   }
76 
resource_provider()77   ResourceProvider* resource_provider() { return resource_provider_.get(); }
78 
ResourceManagerAssertInvariants(PrioritizedResourceManager * resource_manager)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 
TextureBackingIsAbovePriorityCutoff(PrioritizedResource * texture)88   bool TextureBackingIsAbovePriorityCutoff(PrioritizedResource* texture) {
89     return texture->backing()->
90         was_above_priority_cutoff_at_last_priority_update();
91   }
92 
EvictedBackingCount(PrioritizedResourceManager * resource_manager)93   size_t EvictedBackingCount(PrioritizedResourceManager* resource_manager) {
94     return resource_manager->evicted_backings_.size();
95   }
96 
BackingResources(PrioritizedResourceManager * resource_manager)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 
TEST_F(PrioritizedResourceTest,RequestTextureExceedingMaxLimit)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 
TEST_F(PrioritizedResourceTest,ChangeMemoryLimits)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 
TEST_F(PrioritizedResourceTest,ReduceWastedMemory)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 
TEST_F(PrioritizedResourceTest,InUseNotWastedMemory)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 
TEST_F(PrioritizedResourceTest,ChangePriorityCutoff)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 
TEST_F(PrioritizedResourceTest,EvictingTexturesInParent)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 
TEST_F(PrioritizedResourceTest,ResourceManagerPartialUpdateTextures)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 
TEST_F(PrioritizedResourceTest,ResourceManagerPrioritiesAreEqual)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 
TEST_F(PrioritizedResourceTest,ResourceManagerDestroyedFirst)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 
TEST_F(PrioritizedResourceTest,TextureMovedToNewManager)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 
TEST_F(PrioritizedResourceTest,RenderSurfacesReduceMemoryAvailableOutsideRootSurface)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 
TEST_F(PrioritizedResourceTest,RenderSurfacesReduceMemoryAvailableForRequestLate)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 
TEST_F(PrioritizedResourceTest,WhenRenderSurfaceNotAvailableTexturesAlsoNotAvailable)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 
TEST_F(PrioritizedResourceTest,RequestLateBackingsSorting)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 
TEST_F(PrioritizedResourceTest,ClearUploadsToEvictedResources)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 
TEST_F(PrioritizedResourceTest,UsageStatistics)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