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: 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 33 virtual ~PrioritizedResourceTest() { 34 DebugScopedSetImplThread impl_thread(&proxy_); 35 resource_provider_.reset(); 36 } 37 38 size_t TexturesMemorySize(size_t texture_count) { 39 return Resource::MemorySizeBytes(texture_size_, texture_format_) * 40 texture_count; 41 } 42 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 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 64 void PrioritizeTexturesAndBackings( 65 PrioritizedResourceManager* resource_manager) { 66 resource_manager->PrioritizeTextures(); 67 ResourceManagerUpdateBackingsPriorities(resource_manager); 68 } 69 70 void ResourceManagerUpdateBackingsPriorities( 71 PrioritizedResourceManager* resource_manager) { 72 DebugScopedSetImplThreadAndMainThreadBlocked 73 impl_thread_and_main_thread_blocked(&proxy_); 74 resource_manager->PushTexturePrioritiesToBackings(); 75 } 76 77 ResourceProvider* resource_provider() { return resource_provider_.get(); } 78 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 88 bool TextureBackingIsAbovePriorityCutoff(PrioritizedResource* texture) { 89 return texture->backing()-> 90 was_above_priority_cutoff_at_last_priority_update(); 91 } 92 93 size_t EvictedBackingCount(PrioritizedResourceManager* resource_manager) { 94 return resource_manager->evicted_backings_.size(); 95 } 96 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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