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/prioritized_resource.h" | |
6 | |
7 #include "cc/prioritized_resource_manager.h" | |
8 #include "cc/resource.h" | |
9 #include "cc/test/fake_output_surface.h" | |
10 #include "cc/test/fake_proxy.h" | |
11 #include "cc/test/tiled_layer_test_common.h" | |
12 #include "cc/trees/single_thread_proxy.h" // For DebugScopedSetImplThread | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 | |
15 namespace cc { | |
16 | |
17 class PrioritizedResourceTest : public testing::Test { | |
18 public: | |
19 PrioritizedResourceTest() | |
20 : m_proxy(scoped_ptr<Thread>(NULL)) | |
21 , m_textureSize(256, 256) | |
22 , m_textureFormat(GL_RGBA) | |
23 , m_outputSurface(createFakeOutputSurface()) | |
24 { | |
25 DebugScopedSetImplThread implThread(&m_proxy); | |
26 m_resourceProvider = ResourceProvider::Create(m_outputSurface.get()); | |
27 } | |
28 | |
29 virtual ~PrioritizedResourceTest() | |
30 { | |
31 DebugScopedSetImplThread implThread(&m_proxy); | |
32 m_resourceProvider.reset(); | |
33 } | |
34 | |
35 size_t texturesMemorySize(size_t textureCount) | |
36 { | |
37 return Resource::MemorySizeBytes(m_textureSize, m_textureFormat) * textu
reCount; | |
38 } | |
39 | |
40 scoped_ptr<PrioritizedResourceManager> createManager(size_t maxTextures) | |
41 { | |
42 scoped_ptr<PrioritizedResourceManager> manager = PrioritizedResourceMana
ger::create(&m_proxy); | |
43 manager->setMaxMemoryLimitBytes(texturesMemorySize(maxTextures)); | |
44 return manager.Pass(); | |
45 } | |
46 | |
47 bool validateTexture(scoped_ptr<PrioritizedResource>& texture, bool requestL
ate) | |
48 { | |
49 resourceManagerAssertInvariants(texture->resourceManager()); | |
50 if (requestLate) | |
51 texture->requestLate(); | |
52 resourceManagerAssertInvariants(texture->resourceManager()); | |
53 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
54 bool success = texture->canAcquireBackingTexture(); | |
55 if (success) | |
56 texture->acquireBackingTexture(resourceProvider()); | |
57 return success; | |
58 } | |
59 | |
60 void prioritizeTexturesAndBackings(PrioritizedResourceManager* resourceManag
er) | |
61 { | |
62 resourceManager->prioritizeTextures(); | |
63 resourceManagerUpdateBackingsPriorities(resourceManager); | |
64 } | |
65 | |
66 void resourceManagerUpdateBackingsPriorities(PrioritizedResourceManager* res
ourceManager) | |
67 { | |
68 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
69 resourceManager->pushTexturePrioritiesToBackings(); | |
70 } | |
71 | |
72 ResourceProvider* resourceProvider() | |
73 { | |
74 return m_resourceProvider.get(); | |
75 } | |
76 | |
77 void resourceManagerAssertInvariants(PrioritizedResourceManager* resourceMan
ager) | |
78 { | |
79 #ifndef NDEBUG | |
80 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
81 resourceManager->assertInvariants(); | |
82 #endif | |
83 } | |
84 | |
85 bool textureBackingIsAbovePriorityCutoff(PrioritizedResource* texture) | |
86 { | |
87 return texture->m_backing->wasAbovePriorityCutoffAtLastPriorityUpdate(); | |
88 } | |
89 | |
90 size_t evictedBackingCount(PrioritizedResourceManager* resourceManager) | |
91 { | |
92 return resourceManager->m_evictedBackings.size(); | |
93 } | |
94 | |
95 protected: | |
96 FakeProxy m_proxy; | |
97 const gfx::Size m_textureSize; | |
98 const GLenum m_textureFormat; | |
99 scoped_ptr<OutputSurface> m_outputSurface; | |
100 scoped_ptr<ResourceProvider> m_resourceProvider; | |
101 }; | |
102 | |
103 namespace { | |
104 | |
105 TEST_F(PrioritizedResourceTest, requestTextureExceedingMaxLimit) | |
106 { | |
107 const size_t maxTextures = 8; | |
108 scoped_ptr<PrioritizedResourceManager> resourceManager = createManager(maxTe
xtures); | |
109 | |
110 // Create textures for double our memory limit. | |
111 scoped_ptr<PrioritizedResource> textures[maxTextures*2]; | |
112 | |
113 for (size_t i = 0; i < maxTextures*2; ++i) | |
114 textures[i] = resourceManager->createTexture(m_textureSize, m_textureFor
mat); | |
115 | |
116 // Set decreasing priorities | |
117 for (size_t i = 0; i < maxTextures*2; ++i) | |
118 textures[i]->setRequestPriority(100 + i); | |
119 | |
120 // Only lower half should be available. | |
121 prioritizeTexturesAndBackings(resourceManager.get()); | |
122 EXPECT_TRUE(validateTexture(textures[0], false)); | |
123 EXPECT_TRUE(validateTexture(textures[7], false)); | |
124 EXPECT_FALSE(validateTexture(textures[8], false)); | |
125 EXPECT_FALSE(validateTexture(textures[15], false)); | |
126 | |
127 // Set increasing priorities | |
128 for (size_t i = 0; i < maxTextures*2; ++i) | |
129 textures[i]->setRequestPriority(100 - i); | |
130 | |
131 // Only upper half should be available. | |
132 prioritizeTexturesAndBackings(resourceManager.get()); | |
133 EXPECT_FALSE(validateTexture(textures[0], false)); | |
134 EXPECT_FALSE(validateTexture(textures[7], false)); | |
135 EXPECT_TRUE(validateTexture(textures[8], false)); | |
136 EXPECT_TRUE(validateTexture(textures[15], false)); | |
137 | |
138 EXPECT_EQ(texturesMemorySize(maxTextures), resourceManager->memoryAboveCutof
fBytes()); | |
139 EXPECT_LE(resourceManager->memoryUseBytes(), resourceManager->memoryAboveCut
offBytes()); | |
140 | |
141 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
142 resourceManager->clearAllMemory(resourceProvider()); | |
143 } | |
144 | |
145 TEST_F(PrioritizedResourceTest, changeMemoryLimits) | |
146 { | |
147 const size_t maxTextures = 8; | |
148 scoped_ptr<PrioritizedResourceManager> resourceManager = createManager(maxTe
xtures); | |
149 scoped_ptr<PrioritizedResource> textures[maxTextures]; | |
150 | |
151 for (size_t i = 0; i < maxTextures; ++i) | |
152 textures[i] = resourceManager->createTexture(m_textureSize, m_textureFor
mat); | |
153 for (size_t i = 0; i < maxTextures; ++i) | |
154 textures[i]->setRequestPriority(100 + i); | |
155 | |
156 // Set max limit to 8 textures | |
157 resourceManager->setMaxMemoryLimitBytes(texturesMemorySize(8)); | |
158 prioritizeTexturesAndBackings(resourceManager.get()); | |
159 for (size_t i = 0; i < maxTextures; ++i) | |
160 validateTexture(textures[i], false); | |
161 { | |
162 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
163 resourceManager->reduceMemory(resourceProvider()); | |
164 } | |
165 | |
166 EXPECT_EQ(texturesMemorySize(8), resourceManager->memoryAboveCutoffBytes()); | |
167 EXPECT_LE(resourceManager->memoryUseBytes(), resourceManager->memoryAboveCut
offBytes()); | |
168 | |
169 // Set max limit to 5 textures | |
170 resourceManager->setMaxMemoryLimitBytes(texturesMemorySize(5)); | |
171 prioritizeTexturesAndBackings(resourceManager.get()); | |
172 for (size_t i = 0; i < maxTextures; ++i) | |
173 EXPECT_EQ(validateTexture(textures[i], false), i < 5); | |
174 { | |
175 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
176 resourceManager->reduceMemory(resourceProvider()); | |
177 } | |
178 | |
179 EXPECT_EQ(texturesMemorySize(5), resourceManager->memoryAboveCutoffBytes()); | |
180 EXPECT_LE(resourceManager->memoryUseBytes(), resourceManager->memoryAboveCut
offBytes()); | |
181 | |
182 // Set max limit to 4 textures | |
183 resourceManager->setMaxMemoryLimitBytes(texturesMemorySize(4)); | |
184 prioritizeTexturesAndBackings(resourceManager.get()); | |
185 for (size_t i = 0; i < maxTextures; ++i) | |
186 EXPECT_EQ(validateTexture(textures[i], false), i < 4); | |
187 { | |
188 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
189 resourceManager->reduceMemory(resourceProvider()); | |
190 } | |
191 | |
192 EXPECT_EQ(texturesMemorySize(4), resourceManager->memoryAboveCutoffBytes()); | |
193 EXPECT_LE(resourceManager->memoryUseBytes(), resourceManager->memoryAboveCut
offBytes()); | |
194 | |
195 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
196 resourceManager->clearAllMemory(resourceProvider()); | |
197 } | |
198 | |
199 TEST_F(PrioritizedResourceTest, changePriorityCutoff) | |
200 { | |
201 const size_t maxTextures = 8; | |
202 scoped_ptr<PrioritizedResourceManager> resourceManager = createManager(maxTe
xtures); | |
203 scoped_ptr<PrioritizedResource> textures[maxTextures]; | |
204 | |
205 for (size_t i = 0; i < maxTextures; ++i) | |
206 textures[i] = resourceManager->createTexture(m_textureSize, m_textureFor
mat); | |
207 for (size_t i = 0; i < maxTextures; ++i) | |
208 textures[i]->setRequestPriority(100 + i); | |
209 | |
210 // Set the cutoff to drop two textures. Try to requestLate on all textures,
and | |
211 // make sure that requestLate doesn't work on a texture with equal priority
to | |
212 // the cutoff. | |
213 resourceManager->setMaxMemoryLimitBytes(texturesMemorySize(8)); | |
214 resourceManager->setExternalPriorityCutoff(106); | |
215 prioritizeTexturesAndBackings(resourceManager.get()); | |
216 for (size_t i = 0; i < maxTextures; ++i) | |
217 EXPECT_EQ(validateTexture(textures[i], true), i < 6); | |
218 { | |
219 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
220 resourceManager->reduceMemory(resourceProvider()); | |
221 } | |
222 EXPECT_EQ(texturesMemorySize(6), resourceManager->memoryAboveCutoffBytes()); | |
223 EXPECT_LE(resourceManager->memoryUseBytes(), resourceManager->memoryAboveCut
offBytes()); | |
224 | |
225 // Set the cutoff to drop two more textures. | |
226 resourceManager->setExternalPriorityCutoff(104); | |
227 prioritizeTexturesAndBackings(resourceManager.get()); | |
228 for (size_t i = 0; i < maxTextures; ++i) | |
229 EXPECT_EQ(validateTexture(textures[i], false), i < 4); | |
230 { | |
231 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
232 resourceManager->reduceMemory(resourceProvider()); | |
233 } | |
234 EXPECT_EQ(texturesMemorySize(4), resourceManager->memoryAboveCutoffBytes()); | |
235 | |
236 // Do a one-time eviction for one more texture based on priority cutoff | |
237 PrioritizedResourceManager::BackingList evictedBackings; | |
238 resourceManager->unlinkAndClearEvictedBackings(); | |
239 { | |
240 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
241 resourceManager->reduceMemoryOnImplThread(texturesMemorySize(8), 104, re
sourceProvider()); | |
242 EXPECT_EQ(0, evictedBackingCount(resourceManager.get())); | |
243 resourceManager->reduceMemoryOnImplThread(texturesMemorySize(8), 103, re
sourceProvider()); | |
244 EXPECT_EQ(1, evictedBackingCount(resourceManager.get())); | |
245 } | |
246 resourceManager->unlinkAndClearEvictedBackings(); | |
247 EXPECT_EQ(texturesMemorySize(3), resourceManager->memoryUseBytes()); | |
248 | |
249 // Re-allocate the the texture after the one-time drop. | |
250 prioritizeTexturesAndBackings(resourceManager.get()); | |
251 for (size_t i = 0; i < maxTextures; ++i) | |
252 EXPECT_EQ(validateTexture(textures[i], false), i < 4); | |
253 { | |
254 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
255 resourceManager->reduceMemory(resourceProvider()); | |
256 } | |
257 EXPECT_EQ(texturesMemorySize(4), resourceManager->memoryAboveCutoffBytes()); | |
258 | |
259 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
260 resourceManager->clearAllMemory(resourceProvider()); | |
261 } | |
262 | |
263 TEST_F(PrioritizedResourceTest, resourceManagerPartialUpdateTextures) | |
264 { | |
265 const size_t maxTextures = 4; | |
266 const size_t numTextures = 4; | |
267 scoped_ptr<PrioritizedResourceManager> resourceManager = createManager(maxTe
xtures); | |
268 scoped_ptr<PrioritizedResource> textures[numTextures]; | |
269 scoped_ptr<PrioritizedResource> moreTextures[numTextures]; | |
270 | |
271 for (size_t i = 0; i < numTextures; ++i) { | |
272 textures[i] = resourceManager->createTexture(m_textureSize, m_textureFor
mat); | |
273 moreTextures[i] = resourceManager->createTexture(m_textureSize, m_textur
eFormat); | |
274 } | |
275 | |
276 for (size_t i = 0; i < numTextures; ++i) | |
277 textures[i]->setRequestPriority(200 + i); | |
278 prioritizeTexturesAndBackings(resourceManager.get()); | |
279 | |
280 // Allocate textures which are currently high priority. | |
281 EXPECT_TRUE(validateTexture(textures[0], false)); | |
282 EXPECT_TRUE(validateTexture(textures[1], false)); | |
283 EXPECT_TRUE(validateTexture(textures[2], false)); | |
284 EXPECT_TRUE(validateTexture(textures[3], false)); | |
285 | |
286 EXPECT_TRUE(textures[0]->haveBackingTexture()); | |
287 EXPECT_TRUE(textures[1]->haveBackingTexture()); | |
288 EXPECT_TRUE(textures[2]->haveBackingTexture()); | |
289 EXPECT_TRUE(textures[3]->haveBackingTexture()); | |
290 | |
291 for (size_t i = 0; i < numTextures; ++i) | |
292 moreTextures[i]->setRequestPriority(100 + i); | |
293 prioritizeTexturesAndBackings(resourceManager.get()); | |
294 | |
295 // Textures are now below cutoff. | |
296 EXPECT_FALSE(validateTexture(textures[0], false)); | |
297 EXPECT_FALSE(validateTexture(textures[1], false)); | |
298 EXPECT_FALSE(validateTexture(textures[2], false)); | |
299 EXPECT_FALSE(validateTexture(textures[3], false)); | |
300 | |
301 // But they are still valid to use. | |
302 EXPECT_TRUE(textures[0]->haveBackingTexture()); | |
303 EXPECT_TRUE(textures[1]->haveBackingTexture()); | |
304 EXPECT_TRUE(textures[2]->haveBackingTexture()); | |
305 EXPECT_TRUE(textures[3]->haveBackingTexture()); | |
306 | |
307 // Higher priority textures are finally needed. | |
308 EXPECT_TRUE(validateTexture(moreTextures[0], false)); | |
309 EXPECT_TRUE(validateTexture(moreTextures[1], false)); | |
310 EXPECT_TRUE(validateTexture(moreTextures[2], false)); | |
311 EXPECT_TRUE(validateTexture(moreTextures[3], false)); | |
312 | |
313 // Lower priority have been fully evicted. | |
314 EXPECT_FALSE(textures[0]->haveBackingTexture()); | |
315 EXPECT_FALSE(textures[1]->haveBackingTexture()); | |
316 EXPECT_FALSE(textures[2]->haveBackingTexture()); | |
317 EXPECT_FALSE(textures[3]->haveBackingTexture()); | |
318 | |
319 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
320 resourceManager->clearAllMemory(resourceProvider()); | |
321 } | |
322 | |
323 TEST_F(PrioritizedResourceTest, resourceManagerPrioritiesAreEqual) | |
324 { | |
325 const size_t maxTextures = 16; | |
326 scoped_ptr<PrioritizedResourceManager> resourceManager = createManager(maxTe
xtures); | |
327 scoped_ptr<PrioritizedResource> textures[maxTextures]; | |
328 | |
329 for (size_t i = 0; i < maxTextures; ++i) | |
330 textures[i] = resourceManager->createTexture(m_textureSize, m_textureFor
mat); | |
331 | |
332 // All 16 textures have the same priority except 2 higher priority. | |
333 for (size_t i = 0; i < maxTextures; ++i) | |
334 textures[i]->setRequestPriority(100); | |
335 textures[0]->setRequestPriority(99); | |
336 textures[1]->setRequestPriority(99); | |
337 | |
338 // Set max limit to 8 textures | |
339 resourceManager->setMaxMemoryLimitBytes(texturesMemorySize(8)); | |
340 prioritizeTexturesAndBackings(resourceManager.get()); | |
341 | |
342 // The two high priority textures should be available, others should not. | |
343 for (size_t i = 0; i < 2; ++i) | |
344 EXPECT_TRUE(validateTexture(textures[i], false)); | |
345 for (size_t i = 2; i < maxTextures; ++i) | |
346 EXPECT_FALSE(validateTexture(textures[i], false)); | |
347 EXPECT_EQ(texturesMemorySize(2), resourceManager->memoryAboveCutoffBytes()); | |
348 EXPECT_LE(resourceManager->memoryUseBytes(), resourceManager->memoryAboveCut
offBytes()); | |
349 | |
350 // Manually reserving textures should only succeed on the higher priority te
xtures, | |
351 // and on remaining textures up to the memory limit. | |
352 for (size_t i = 0; i < 8; i++) | |
353 EXPECT_TRUE(validateTexture(textures[i], true)); | |
354 for (size_t i = 9; i < maxTextures; i++) | |
355 EXPECT_FALSE(validateTexture(textures[i], true)); | |
356 EXPECT_EQ(texturesMemorySize(8), resourceManager->memoryAboveCutoffBytes()); | |
357 EXPECT_LE(resourceManager->memoryUseBytes(), resourceManager->memoryAboveCut
offBytes()); | |
358 | |
359 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
360 resourceManager->clearAllMemory(resourceProvider()); | |
361 } | |
362 | |
363 TEST_F(PrioritizedResourceTest, resourceManagerDestroyedFirst) | |
364 { | |
365 scoped_ptr<PrioritizedResourceManager> resourceManager = createManager(1); | |
366 scoped_ptr<PrioritizedResource> texture = resourceManager->createTexture(m_t
extureSize, m_textureFormat); | |
367 | |
368 // Texture is initially invalid, but it will become available. | |
369 EXPECT_FALSE(texture->haveBackingTexture()); | |
370 | |
371 texture->setRequestPriority(100); | |
372 prioritizeTexturesAndBackings(resourceManager.get()); | |
373 | |
374 EXPECT_TRUE(validateTexture(texture, false)); | |
375 EXPECT_TRUE(texture->canAcquireBackingTexture()); | |
376 EXPECT_TRUE(texture->haveBackingTexture()); | |
377 | |
378 { | |
379 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
380 resourceManager->clearAllMemory(resourceProvider()); | |
381 } | |
382 resourceManager.reset(); | |
383 | |
384 EXPECT_FALSE(texture->canAcquireBackingTexture()); | |
385 EXPECT_FALSE(texture->haveBackingTexture()); | |
386 } | |
387 | |
388 TEST_F(PrioritizedResourceTest, textureMovedToNewManager) | |
389 { | |
390 scoped_ptr<PrioritizedResourceManager> resourceManagerOne = createManager(1)
; | |
391 scoped_ptr<PrioritizedResourceManager> resourceManagerTwo = createManager(1)
; | |
392 scoped_ptr<PrioritizedResource> texture = resourceManagerOne->createTexture(
m_textureSize, m_textureFormat); | |
393 | |
394 // Texture is initially invalid, but it will become available. | |
395 EXPECT_FALSE(texture->haveBackingTexture()); | |
396 | |
397 texture->setRequestPriority(100); | |
398 prioritizeTexturesAndBackings(resourceManagerOne.get()); | |
399 | |
400 EXPECT_TRUE(validateTexture(texture, false)); | |
401 EXPECT_TRUE(texture->canAcquireBackingTexture()); | |
402 EXPECT_TRUE(texture->haveBackingTexture()); | |
403 | |
404 texture->setTextureManager(0); | |
405 | |
406 { | |
407 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
408 resourceManagerOne->clearAllMemory(resourceProvider()); | |
409 } | |
410 resourceManagerOne.reset(); | |
411 | |
412 EXPECT_FALSE(texture->canAcquireBackingTexture()); | |
413 EXPECT_FALSE(texture->haveBackingTexture()); | |
414 | |
415 texture->setTextureManager(resourceManagerTwo.get()); | |
416 | |
417 prioritizeTexturesAndBackings(resourceManagerTwo.get()); | |
418 | |
419 EXPECT_TRUE(validateTexture(texture, false)); | |
420 EXPECT_TRUE(texture->canAcquireBackingTexture()); | |
421 EXPECT_TRUE(texture->haveBackingTexture()); | |
422 | |
423 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
424 resourceManagerTwo->clearAllMemory(resourceProvider()); | |
425 } | |
426 | |
427 TEST_F(PrioritizedResourceTest, renderSurfacesReduceMemoryAvailableOutsideRootSu
rface) | |
428 { | |
429 const size_t maxTextures = 8; | |
430 scoped_ptr<PrioritizedResourceManager> resourceManager = createManager(maxTe
xtures); | |
431 | |
432 // Half of the memory is taken by surfaces (with high priority place-holder) | |
433 scoped_ptr<PrioritizedResource> renderSurfacePlaceHolder = resourceManager->
createTexture(m_textureSize, m_textureFormat); | |
434 renderSurfacePlaceHolder->setToSelfManagedMemoryPlaceholder(texturesMemorySi
ze(4)); | |
435 renderSurfacePlaceHolder->setRequestPriority(PriorityCalculator::RenderSurfa
cePriority()); | |
436 | |
437 // Create textures to fill our memory limit. | |
438 scoped_ptr<PrioritizedResource> textures[maxTextures]; | |
439 | |
440 for (size_t i = 0; i < maxTextures; ++i) | |
441 textures[i] = resourceManager->createTexture(m_textureSize, m_textureFor
mat); | |
442 | |
443 // Set decreasing non-visible priorities outside root surface. | |
444 for (size_t i = 0; i < maxTextures; ++i) | |
445 textures[i]->setRequestPriority(100 + i); | |
446 | |
447 // Only lower half should be available. | |
448 prioritizeTexturesAndBackings(resourceManager.get()); | |
449 EXPECT_TRUE(validateTexture(textures[0], false)); | |
450 EXPECT_TRUE(validateTexture(textures[3], false)); | |
451 EXPECT_FALSE(validateTexture(textures[4], false)); | |
452 EXPECT_FALSE(validateTexture(textures[7], false)); | |
453 | |
454 // Set increasing non-visible priorities outside root surface. | |
455 for (size_t i = 0; i < maxTextures; ++i) | |
456 textures[i]->setRequestPriority(100 - i); | |
457 | |
458 // Only upper half should be available. | |
459 prioritizeTexturesAndBackings(resourceManager.get()); | |
460 EXPECT_FALSE(validateTexture(textures[0], false)); | |
461 EXPECT_FALSE(validateTexture(textures[3], false)); | |
462 EXPECT_TRUE(validateTexture(textures[4], false)); | |
463 EXPECT_TRUE(validateTexture(textures[7], false)); | |
464 | |
465 EXPECT_EQ(texturesMemorySize(4), resourceManager->memoryAboveCutoffBytes()); | |
466 EXPECT_EQ(texturesMemorySize(4), resourceManager->memoryForSelfManagedTextur
es()); | |
467 EXPECT_LE(resourceManager->memoryUseBytes(), resourceManager->memoryAboveCut
offBytes()); | |
468 | |
469 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
470 resourceManager->clearAllMemory(resourceProvider()); | |
471 } | |
472 | |
473 TEST_F(PrioritizedResourceTest, renderSurfacesReduceMemoryAvailableForRequestLat
e) | |
474 { | |
475 const size_t maxTextures = 8; | |
476 scoped_ptr<PrioritizedResourceManager> resourceManager = createManager(maxTe
xtures); | |
477 | |
478 // Half of the memory is taken by surfaces (with high priority place-holder) | |
479 scoped_ptr<PrioritizedResource> renderSurfacePlaceHolder = resourceManager->
createTexture(m_textureSize, m_textureFormat); | |
480 renderSurfacePlaceHolder->setToSelfManagedMemoryPlaceholder(texturesMemorySi
ze(4)); | |
481 renderSurfacePlaceHolder->setRequestPriority(PriorityCalculator::RenderSurfa
cePriority()); | |
482 | |
483 // Create textures to fill our memory limit. | |
484 scoped_ptr<PrioritizedResource> textures[maxTextures]; | |
485 | |
486 for (size_t i = 0; i < maxTextures; ++i) | |
487 textures[i] = resourceManager->createTexture(m_textureSize, m_textureFor
mat); | |
488 | |
489 // Set equal priorities. | |
490 for (size_t i = 0; i < maxTextures; ++i) | |
491 textures[i]->setRequestPriority(100); | |
492 | |
493 // The first four to be requested late will be available. | |
494 prioritizeTexturesAndBackings(resourceManager.get()); | |
495 for (unsigned i = 0; i < maxTextures; ++i) | |
496 EXPECT_FALSE(validateTexture(textures[i], false)); | |
497 for (unsigned i = 0; i < maxTextures; i += 2) | |
498 EXPECT_TRUE(validateTexture(textures[i], true)); | |
499 for (unsigned i = 1; i < maxTextures; i += 2) | |
500 EXPECT_FALSE(validateTexture(textures[i], true)); | |
501 | |
502 EXPECT_EQ(texturesMemorySize(4), resourceManager->memoryAboveCutoffBytes()); | |
503 EXPECT_EQ(texturesMemorySize(4), resourceManager->memoryForSelfManagedTextur
es()); | |
504 EXPECT_LE(resourceManager->memoryUseBytes(), resourceManager->memoryAboveCut
offBytes()); | |
505 | |
506 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
507 resourceManager->clearAllMemory(resourceProvider()); | |
508 } | |
509 | |
510 TEST_F(PrioritizedResourceTest, whenRenderSurfaceNotAvailableTexturesAlsoNotAvai
lable) | |
511 { | |
512 const size_t maxTextures = 8; | |
513 scoped_ptr<PrioritizedResourceManager> resourceManager = createManager(maxTe
xtures); | |
514 | |
515 // Half of the memory is taken by surfaces (with high priority place-holder) | |
516 scoped_ptr<PrioritizedResource> renderSurfacePlaceHolder = resourceManager->
createTexture(m_textureSize, m_textureFormat); | |
517 renderSurfacePlaceHolder->setToSelfManagedMemoryPlaceholder(texturesMemorySi
ze(4)); | |
518 renderSurfacePlaceHolder->setRequestPriority(PriorityCalculator::RenderSurfa
cePriority()); | |
519 | |
520 // Create textures to fill our memory limit. | |
521 scoped_ptr<PrioritizedResource> textures[maxTextures]; | |
522 | |
523 for (size_t i = 0; i < maxTextures; ++i) | |
524 textures[i] = resourceManager->createTexture(m_textureSize, m_textureFor
mat); | |
525 | |
526 // Set 6 visible textures in the root surface, and 2 in a child surface. | |
527 for (size_t i = 0; i < 6; ++i) | |
528 textures[i]->setRequestPriority(PriorityCalculator::VisiblePriority(true
)); | |
529 for (size_t i = 6; i < 8; ++i) | |
530 textures[i]->setRequestPriority(PriorityCalculator::VisiblePriority(fals
e)); | |
531 | |
532 prioritizeTexturesAndBackings(resourceManager.get()); | |
533 | |
534 // Unable to requestLate textures in the child surface. | |
535 EXPECT_FALSE(validateTexture(textures[6], true)); | |
536 EXPECT_FALSE(validateTexture(textures[7], true)); | |
537 | |
538 // Root surface textures are valid. | |
539 for (size_t i = 0; i < 6; ++i) | |
540 EXPECT_TRUE(validateTexture(textures[i], false)); | |
541 | |
542 EXPECT_EQ(texturesMemorySize(6), resourceManager->memoryAboveCutoffBytes()); | |
543 EXPECT_EQ(texturesMemorySize(2), resourceManager->memoryForSelfManagedTextur
es()); | |
544 EXPECT_LE(resourceManager->memoryUseBytes(), resourceManager->memoryAboveCut
offBytes()); | |
545 | |
546 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
547 resourceManager->clearAllMemory(resourceProvider()); | |
548 } | |
549 | |
550 TEST_F(PrioritizedResourceTest, requestLateBackingsSorting) | |
551 { | |
552 const size_t maxTextures = 8; | |
553 scoped_ptr<PrioritizedResourceManager> resourceManager = createManager(maxTe
xtures); | |
554 resourceManager->setMaxMemoryLimitBytes(texturesMemorySize(maxTextures)); | |
555 | |
556 // Create textures to fill our memory limit. | |
557 scoped_ptr<PrioritizedResource> textures[maxTextures]; | |
558 for (size_t i = 0; i < maxTextures; ++i) | |
559 textures[i] = resourceManager->createTexture(m_textureSize, m_textureFor
mat); | |
560 | |
561 // Set equal priorities, and allocate backings for all textures. | |
562 for (size_t i = 0; i < maxTextures; ++i) | |
563 textures[i]->setRequestPriority(100); | |
564 prioritizeTexturesAndBackings(resourceManager.get()); | |
565 for (unsigned i = 0; i < maxTextures; ++i) | |
566 EXPECT_TRUE(validateTexture(textures[i], false)); | |
567 | |
568 // Drop the memory limit and prioritize (none will be above the threshold, | |
569 // but they still have backings because reduceMemory hasn't been called). | |
570 resourceManager->setMaxMemoryLimitBytes(texturesMemorySize(maxTextures / 2))
; | |
571 prioritizeTexturesAndBackings(resourceManager.get()); | |
572 | |
573 // Push half of them back over the limit. | |
574 for (size_t i = 0; i < maxTextures; i += 2) | |
575 EXPECT_TRUE(textures[i]->requestLate()); | |
576 | |
577 // Push the priorities to the backings array and sort the backings array | |
578 resourceManagerUpdateBackingsPriorities(resourceManager.get()); | |
579 | |
580 // Assert that the backings list be sorted with the below-limit backings | |
581 // before the above-limit backings. | |
582 resourceManagerAssertInvariants(resourceManager.get()); | |
583 | |
584 // Make sure that we have backings for all of the textures. | |
585 for (size_t i = 0; i < maxTextures; ++i) | |
586 EXPECT_TRUE(textures[i]->haveBackingTexture()); | |
587 | |
588 // Make sure that only the requestLate textures are above the priority cutof
f | |
589 for (size_t i = 0; i < maxTextures; i += 2) | |
590 EXPECT_TRUE(textureBackingIsAbovePriorityCutoff(textures[i].get())); | |
591 for (size_t i = 1; i < maxTextures; i += 2) | |
592 EXPECT_FALSE(textureBackingIsAbovePriorityCutoff(textures[i].get())); | |
593 | |
594 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
595 resourceManager->clearAllMemory(resourceProvider()); | |
596 } | |
597 | |
598 TEST_F(PrioritizedResourceTest, clearUploadsToEvictedResources) | |
599 { | |
600 const size_t maxTextures = 4; | |
601 scoped_ptr<PrioritizedResourceManager> resourceManager = | |
602 createManager(maxTextures); | |
603 resourceManager->setMaxMemoryLimitBytes(texturesMemorySize(maxTextures)); | |
604 | |
605 // Create textures to fill our memory limit. | |
606 scoped_ptr<PrioritizedResource> textures[maxTextures]; | |
607 | |
608 for (size_t i = 0; i < maxTextures; ++i) | |
609 textures[i] = resourceManager->createTexture(m_textureSize, m_textureFor
mat); | |
610 | |
611 // Set equal priorities, and allocate backings for all textures. | |
612 for (size_t i = 0; i < maxTextures; ++i) | |
613 textures[i]->setRequestPriority(100); | |
614 prioritizeTexturesAndBackings(resourceManager.get()); | |
615 for (unsigned i = 0; i < maxTextures; ++i) | |
616 EXPECT_TRUE(validateTexture(textures[i], false)); | |
617 | |
618 ResourceUpdateQueue queue; | |
619 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
620 for (size_t i = 0; i < maxTextures; ++i) { | |
621 const ResourceUpdate upload = ResourceUpdate::Create( | |
622 textures[i].get(), NULL, gfx::Rect(), gfx::Rect(), gfx::Vector2d()); | |
623 queue.appendFullUpload(upload); | |
624 } | |
625 | |
626 // Make sure that we have backings for all of the textures. | |
627 for (size_t i = 0; i < maxTextures; ++i) | |
628 EXPECT_TRUE(textures[i]->haveBackingTexture()); | |
629 | |
630 queue.clearUploadsToEvictedResources(); | |
631 EXPECT_EQ(4, queue.fullUploadSize()); | |
632 | |
633 resourceManager->reduceMemoryOnImplThread( | |
634 texturesMemorySize(1), PriorityCalculator::AllowEverythingCutoff(), reso
urceProvider()); | |
635 queue.clearUploadsToEvictedResources(); | |
636 EXPECT_EQ(1, queue.fullUploadSize()); | |
637 | |
638 resourceManager->reduceMemoryOnImplThread(0, PriorityCalculator::AllowEvery
thingCutoff(), resourceProvider()); | |
639 queue.clearUploadsToEvictedResources(); | |
640 EXPECT_EQ(0, queue.fullUploadSize()); | |
641 | |
642 } | |
643 | |
644 TEST_F(PrioritizedResourceTest, usageStatistics) | |
645 { | |
646 const size_t maxTextures = 5; | |
647 scoped_ptr<PrioritizedResourceManager> resourceManager = createManager(maxTe
xtures); | |
648 scoped_ptr<PrioritizedResource> textures[maxTextures]; | |
649 | |
650 for (size_t i = 0; i < maxTextures; ++i) | |
651 textures[i] = resourceManager->createTexture(m_textureSize, m_textureFor
mat); | |
652 | |
653 textures[0]->setRequestPriority(PriorityCalculator::AllowVisibleOnlyCutoff()
- 1); | |
654 textures[1]->setRequestPriority(PriorityCalculator::AllowVisibleOnlyCutoff()
); | |
655 textures[2]->setRequestPriority(PriorityCalculator::AllowVisibleAndNearbyCut
off() - 1); | |
656 textures[3]->setRequestPriority(PriorityCalculator::AllowVisibleAndNearbyCut
off()); | |
657 textures[4]->setRequestPriority(PriorityCalculator::AllowVisibleAndNearbyCut
off() + 1); | |
658 | |
659 // Set max limit to 2 textures. | |
660 resourceManager->setMaxMemoryLimitBytes(texturesMemorySize(2)); | |
661 prioritizeTexturesAndBackings(resourceManager.get()); | |
662 | |
663 // The first two textures should be available, others should not. | |
664 for (size_t i = 0; i < 2; ++i) | |
665 EXPECT_TRUE(validateTexture(textures[i], false)); | |
666 for (size_t i = 2; i < maxTextures; ++i) | |
667 EXPECT_FALSE(validateTexture(textures[i], false)); | |
668 | |
669 // Validate the statistics. | |
670 { | |
671 DebugScopedSetImplThread implThread(&m_proxy); | |
672 EXPECT_EQ(texturesMemorySize(2), resourceManager->memoryUseBytes()); | |
673 EXPECT_EQ(texturesMemorySize(1), resourceManager->memoryVisibleBytes()); | |
674 EXPECT_EQ(texturesMemorySize(3), resourceManager->memoryVisibleAndNearby
Bytes()); | |
675 } | |
676 | |
677 // Re-prioritize the textures, but do not push the values to backings. | |
678 textures[0]->setRequestPriority(PriorityCalculator::AllowVisibleOnlyCutoff()
- 1); | |
679 textures[1]->setRequestPriority(PriorityCalculator::AllowVisibleOnlyCutoff()
- 1); | |
680 textures[2]->setRequestPriority(PriorityCalculator::AllowVisibleOnlyCutoff()
- 1); | |
681 textures[3]->setRequestPriority(PriorityCalculator::AllowVisibleAndNearbyCut
off() - 1); | |
682 textures[4]->setRequestPriority(PriorityCalculator::AllowVisibleAndNearbyCut
off()); | |
683 resourceManager->prioritizeTextures(); | |
684 | |
685 // Verify that we still see the old values. | |
686 { | |
687 DebugScopedSetImplThread implThread(&m_proxy); | |
688 EXPECT_EQ(texturesMemorySize(2), resourceManager->memoryUseBytes()); | |
689 EXPECT_EQ(texturesMemorySize(1), resourceManager->memoryVisibleBytes()); | |
690 EXPECT_EQ(texturesMemorySize(3), resourceManager->memoryVisibleAndNearby
Bytes()); | |
691 } | |
692 | |
693 // Push priorities to backings, and verify we see the new values. | |
694 { | |
695 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked(&m_proxy); | |
696 resourceManager->pushTexturePrioritiesToBackings(); | |
697 EXPECT_EQ(texturesMemorySize(2), resourceManager->memoryUseBytes()); | |
698 EXPECT_EQ(texturesMemorySize(3), resourceManager->memoryVisibleBytes()); | |
699 EXPECT_EQ(texturesMemorySize(4), resourceManager->memoryVisibleAndNearby
Bytes()); | |
700 } | |
701 | |
702 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked(
&m_proxy); | |
703 resourceManager->clearAllMemory(resourceProvider()); | |
704 } | |
705 | |
706 } // namespace | |
707 } // namespace cc | |
OLD | NEW |