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
20namespace cc {
21
22class 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
123namespace {
124
125TEST_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
171TEST_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
238TEST_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
308TEST_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
388TEST_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
461TEST_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
604TEST_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
667TEST_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
712TEST_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
737TEST_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
779TEST_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
836TEST_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
884TEST_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
936TEST_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
988TEST_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
1037TEST_F(PrioritizedResourceTest, UsageStatistics) {
1038  const size_t kMaxTextures = 5;
1039  scoped_ptr<PrioritizedResourceManager> resource_manager =
1040      CreateManager(kMaxTextures);
1041  scoped_ptr<PrioritizedResource> textures[kMaxTextures];
1042
1043  for (size_t i = 0; i < kMaxTextures; ++i) {
1044    textures[i] =
1045        resource_manager->CreateTexture(texture_size_, texture_format_);
1046  }
1047
1048  textures[0]->
1049      set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
1050  textures[1]->
1051      set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff());
1052  textures[2]->set_request_priority(
1053      PriorityCalculator::AllowVisibleAndNearbyCutoff() - 1);
1054  textures[3]->
1055      set_request_priority(PriorityCalculator::AllowVisibleAndNearbyCutoff());
1056  textures[4]->set_request_priority(
1057      PriorityCalculator::AllowVisibleAndNearbyCutoff() + 1);
1058
1059  // Set max limit to 2 textures.
1060  resource_manager->SetMaxMemoryLimitBytes(TexturesMemorySize(2));
1061  PrioritizeTexturesAndBackings(resource_manager.get());
1062
1063  // The first two textures should be available, others should not.
1064  for (size_t i = 0; i < 2; ++i)
1065    EXPECT_TRUE(ValidateTexture(textures[i].get(), false));
1066  for (size_t i = 2; i < kMaxTextures; ++i)
1067    EXPECT_FALSE(ValidateTexture(textures[i].get(), false));
1068
1069  // Validate the statistics.
1070  {
1071    DebugScopedSetImplThread impl_thread(&proxy_);
1072    EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes());
1073    EXPECT_EQ(TexturesMemorySize(1), resource_manager->MemoryVisibleBytes());
1074    EXPECT_EQ(TexturesMemorySize(3),
1075              resource_manager->MemoryVisibleAndNearbyBytes());
1076  }
1077
1078  // Re-prioritize the textures, but do not push the values to backings.
1079  textures[0]->
1080      set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
1081  textures[1]->
1082      set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
1083  textures[2]->
1084      set_request_priority(PriorityCalculator::AllowVisibleOnlyCutoff() - 1);
1085  textures[3]->set_request_priority(
1086      PriorityCalculator::AllowVisibleAndNearbyCutoff() - 1);
1087  textures[4]->
1088      set_request_priority(PriorityCalculator::AllowVisibleAndNearbyCutoff());
1089  resource_manager->PrioritizeTextures();
1090
1091  // Verify that we still see the old values.
1092  {
1093    DebugScopedSetImplThread impl_thread(&proxy_);
1094    EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes());
1095    EXPECT_EQ(TexturesMemorySize(1), resource_manager->MemoryVisibleBytes());
1096    EXPECT_EQ(TexturesMemorySize(3),
1097              resource_manager->MemoryVisibleAndNearbyBytes());
1098  }
1099
1100  // Push priorities to backings, and verify we see the new values.
1101  {
1102    DebugScopedSetImplThreadAndMainThreadBlocked
1103        impl_thread_and_main_thread_blocked(&proxy_);
1104    resource_manager->PushTexturePrioritiesToBackings();
1105    EXPECT_EQ(TexturesMemorySize(2), resource_manager->MemoryUseBytes());
1106    EXPECT_EQ(TexturesMemorySize(3), resource_manager->MemoryVisibleBytes());
1107    EXPECT_EQ(TexturesMemorySize(4),
1108              resource_manager->MemoryVisibleAndNearbyBytes());
1109  }
1110
1111  DebugScopedSetImplThreadAndMainThreadBlocked
1112      impl_thread_and_main_thread_blocked(&proxy_);
1113  resource_manager->ClearAllMemory(resource_provider());
1114}
1115
1116}  // namespace
1117}  // namespace cc
1118