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