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