OLD | NEW |
| (Empty) |
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 NULL, | |
35 0, | |
36 false, | |
37 1); | |
38 } | |
39 | |
40 ~PrioritizedResourceTest() override { | |
41 DebugScopedSetImplThread impl_thread(&proxy_); | |
42 resource_provider_ = nullptr; | |
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] = nullptr; | |
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] = nullptr; | |
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] = nullptr; | |
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] = nullptr; | |
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 = nullptr; | |
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 = nullptr; | |
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 | |
OLD | NEW |