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