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.
5 #include "cc/prioritized_resource.h"
7 #include "cc/prioritized_resource_manager.h"
8 #include "cc/resource.h"
9 #include "cc/single_thread_proxy.h" // For DebugScopedSetImplThread
10 #include "cc/test/fake_output_surface.h"
11 #include "cc/test/fake_proxy.h"
12 #include "cc/test/tiled_layer_test_common.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 class PrioritizedResourceTest
: public testing::Test
{
19 PrioritizedResourceTest()
20 : m_proxy(scoped_ptr
<Thread
>(NULL
))
21 , m_textureSize(256, 256)
22 , m_textureFormat(GL_RGBA
)
23 , m_outputSurface(createFakeOutputSurface())
25 DebugScopedSetImplThread
implThread(&m_proxy
);
26 m_resourceProvider
= ResourceProvider::create(m_outputSurface
.get());
29 virtual ~PrioritizedResourceTest()
31 DebugScopedSetImplThread
implThread(&m_proxy
);
32 m_resourceProvider
.reset();
35 size_t texturesMemorySize(size_t textureCount
)
37 return Resource::MemorySizeBytes(m_textureSize
, m_textureFormat
) * textureCount
;
40 scoped_ptr
<PrioritizedResourceManager
> createManager(size_t maxTextures
)
42 scoped_ptr
<PrioritizedResourceManager
> manager
= PrioritizedResourceManager::create(&m_proxy
);
43 manager
->setMaxMemoryLimitBytes(texturesMemorySize(maxTextures
));
44 return manager
.Pass();
47 bool validateTexture(scoped_ptr
<PrioritizedResource
>& texture
, bool requestLate
)
49 resourceManagerAssertInvariants(texture
->resourceManager());
51 texture
->requestLate();
52 resourceManagerAssertInvariants(texture
->resourceManager());
53 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
54 bool success
= texture
->canAcquireBackingTexture();
56 texture
->acquireBackingTexture(resourceProvider());
60 void prioritizeTexturesAndBackings(PrioritizedResourceManager
* resourceManager
)
62 resourceManager
->prioritizeTextures();
63 resourceManagerUpdateBackingsPriorities(resourceManager
);
66 void resourceManagerUpdateBackingsPriorities(PrioritizedResourceManager
* resourceManager
)
68 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
69 resourceManager
->pushTexturePrioritiesToBackings();
72 ResourceProvider
* resourceProvider()
74 return m_resourceProvider
.get();
77 void resourceManagerAssertInvariants(PrioritizedResourceManager
* resourceManager
)
80 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
81 resourceManager
->assertInvariants();
85 bool textureBackingIsAbovePriorityCutoff(PrioritizedResource
* texture
)
87 return texture
->m_backing
->wasAbovePriorityCutoffAtLastPriorityUpdate();
90 size_t evictedBackingCount(PrioritizedResourceManager
* resourceManager
)
92 return resourceManager
->m_evictedBackings
.size();
97 const gfx::Size m_textureSize
;
98 const GLenum m_textureFormat
;
99 scoped_ptr
<OutputSurface
> m_outputSurface
;
100 scoped_ptr
<ResourceProvider
> m_resourceProvider
;
105 TEST_F(PrioritizedResourceTest
, requestTextureExceedingMaxLimit
)
107 const size_t maxTextures
= 8;
108 scoped_ptr
<PrioritizedResourceManager
> resourceManager
= createManager(maxTextures
);
110 // Create textures for double our memory limit.
111 scoped_ptr
<PrioritizedResource
> textures
[maxTextures
*2];
113 for (size_t i
= 0; i
< maxTextures
*2; ++i
)
114 textures
[i
] = resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
116 // Set decreasing priorities
117 for (size_t i
= 0; i
< maxTextures
*2; ++i
)
118 textures
[i
]->setRequestPriority(100 + i
);
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));
127 // Set increasing priorities
128 for (size_t i
= 0; i
< maxTextures
*2; ++i
)
129 textures
[i
]->setRequestPriority(100 - i
);
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));
138 EXPECT_EQ(texturesMemorySize(maxTextures
), resourceManager
->memoryAboveCutoffBytes());
139 EXPECT_LE(resourceManager
->memoryUseBytes(), resourceManager
->memoryAboveCutoffBytes());
141 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
142 resourceManager
->clearAllMemory(resourceProvider());
145 TEST_F(PrioritizedResourceTest
, changeMemoryLimits
)
147 const size_t maxTextures
= 8;
148 scoped_ptr
<PrioritizedResourceManager
> resourceManager
= createManager(maxTextures
);
149 scoped_ptr
<PrioritizedResource
> textures
[maxTextures
];
151 for (size_t i
= 0; i
< maxTextures
; ++i
)
152 textures
[i
] = resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
153 for (size_t i
= 0; i
< maxTextures
; ++i
)
154 textures
[i
]->setRequestPriority(100 + i
);
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);
162 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
163 resourceManager
->reduceMemory(resourceProvider());
166 EXPECT_EQ(texturesMemorySize(8), resourceManager
->memoryAboveCutoffBytes());
167 EXPECT_LE(resourceManager
->memoryUseBytes(), resourceManager
->memoryAboveCutoffBytes());
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);
175 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
176 resourceManager
->reduceMemory(resourceProvider());
179 EXPECT_EQ(texturesMemorySize(5), resourceManager
->memoryAboveCutoffBytes());
180 EXPECT_LE(resourceManager
->memoryUseBytes(), resourceManager
->memoryAboveCutoffBytes());
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);
188 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
189 resourceManager
->reduceMemory(resourceProvider());
192 EXPECT_EQ(texturesMemorySize(4), resourceManager
->memoryAboveCutoffBytes());
193 EXPECT_LE(resourceManager
->memoryUseBytes(), resourceManager
->memoryAboveCutoffBytes());
195 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
196 resourceManager
->clearAllMemory(resourceProvider());
199 TEST_F(PrioritizedResourceTest
, changePriorityCutoff
)
201 const size_t maxTextures
= 8;
202 scoped_ptr
<PrioritizedResourceManager
> resourceManager
= createManager(maxTextures
);
203 scoped_ptr
<PrioritizedResource
> textures
[maxTextures
];
205 for (size_t i
= 0; i
< maxTextures
; ++i
)
206 textures
[i
] = resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
207 for (size_t i
= 0; i
< maxTextures
; ++i
)
208 textures
[i
]->setRequestPriority(100 + i
);
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
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);
219 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
220 resourceManager
->reduceMemory(resourceProvider());
222 EXPECT_EQ(texturesMemorySize(6), resourceManager
->memoryAboveCutoffBytes());
223 EXPECT_LE(resourceManager
->memoryUseBytes(), resourceManager
->memoryAboveCutoffBytes());
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);
231 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
232 resourceManager
->reduceMemory(resourceProvider());
234 EXPECT_EQ(texturesMemorySize(4), resourceManager
->memoryAboveCutoffBytes());
236 // Do a one-time eviction for one more texture based on priority cutoff
237 PrioritizedResourceManager::BackingList evictedBackings
;
238 resourceManager
->unlinkAndClearEvictedBackings();
240 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
241 resourceManager
->reduceMemoryOnImplThread(texturesMemorySize(8), 104, resourceProvider());
242 EXPECT_EQ(0, evictedBackingCount(resourceManager
.get()));
243 resourceManager
->reduceMemoryOnImplThread(texturesMemorySize(8), 103, resourceProvider());
244 EXPECT_EQ(1, evictedBackingCount(resourceManager
.get()));
246 resourceManager
->unlinkAndClearEvictedBackings();
247 EXPECT_EQ(texturesMemorySize(3), resourceManager
->memoryUseBytes());
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);
254 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
255 resourceManager
->reduceMemory(resourceProvider());
257 EXPECT_EQ(texturesMemorySize(4), resourceManager
->memoryAboveCutoffBytes());
259 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
260 resourceManager
->clearAllMemory(resourceProvider());
263 TEST_F(PrioritizedResourceTest
, resourceManagerPartialUpdateTextures
)
265 const size_t maxTextures
= 4;
266 const size_t numTextures
= 4;
267 scoped_ptr
<PrioritizedResourceManager
> resourceManager
= createManager(maxTextures
);
268 scoped_ptr
<PrioritizedResource
> textures
[numTextures
];
269 scoped_ptr
<PrioritizedResource
> moreTextures
[numTextures
];
271 for (size_t i
= 0; i
< numTextures
; ++i
) {
272 textures
[i
] = resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
273 moreTextures
[i
] = resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
276 for (size_t i
= 0; i
< numTextures
; ++i
)
277 textures
[i
]->setRequestPriority(200 + i
);
278 prioritizeTexturesAndBackings(resourceManager
.get());
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));
286 EXPECT_TRUE(textures
[0]->haveBackingTexture());
287 EXPECT_TRUE(textures
[1]->haveBackingTexture());
288 EXPECT_TRUE(textures
[2]->haveBackingTexture());
289 EXPECT_TRUE(textures
[3]->haveBackingTexture());
291 for (size_t i
= 0; i
< numTextures
; ++i
)
292 moreTextures
[i
]->setRequestPriority(100 + i
);
293 prioritizeTexturesAndBackings(resourceManager
.get());
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));
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());
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));
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());
319 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
320 resourceManager
->clearAllMemory(resourceProvider());
323 TEST_F(PrioritizedResourceTest
, resourceManagerPrioritiesAreEqual
)
325 const size_t maxTextures
= 16;
326 scoped_ptr
<PrioritizedResourceManager
> resourceManager
= createManager(maxTextures
);
327 scoped_ptr
<PrioritizedResource
> textures
[maxTextures
];
329 for (size_t i
= 0; i
< maxTextures
; ++i
)
330 textures
[i
] = resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
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);
338 // Set max limit to 8 textures
339 resourceManager
->setMaxMemoryLimitBytes(texturesMemorySize(8));
340 prioritizeTexturesAndBackings(resourceManager
.get());
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
->memoryAboveCutoffBytes());
350 // Manually reserving textures should only succeed on the higher priority textures,
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
->memoryAboveCutoffBytes());
359 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
360 resourceManager
->clearAllMemory(resourceProvider());
363 TEST_F(PrioritizedResourceTest
, resourceManagerDestroyedFirst
)
365 scoped_ptr
<PrioritizedResourceManager
> resourceManager
= createManager(1);
366 scoped_ptr
<PrioritizedResource
> texture
= resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
368 // Texture is initially invalid, but it will become available.
369 EXPECT_FALSE(texture
->haveBackingTexture());
371 texture
->setRequestPriority(100);
372 prioritizeTexturesAndBackings(resourceManager
.get());
374 EXPECT_TRUE(validateTexture(texture
, false));
375 EXPECT_TRUE(texture
->canAcquireBackingTexture());
376 EXPECT_TRUE(texture
->haveBackingTexture());
379 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
380 resourceManager
->clearAllMemory(resourceProvider());
382 resourceManager
.reset();
384 EXPECT_FALSE(texture
->canAcquireBackingTexture());
385 EXPECT_FALSE(texture
->haveBackingTexture());
388 TEST_F(PrioritizedResourceTest
, textureMovedToNewManager
)
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
);
394 // Texture is initially invalid, but it will become available.
395 EXPECT_FALSE(texture
->haveBackingTexture());
397 texture
->setRequestPriority(100);
398 prioritizeTexturesAndBackings(resourceManagerOne
.get());
400 EXPECT_TRUE(validateTexture(texture
, false));
401 EXPECT_TRUE(texture
->canAcquireBackingTexture());
402 EXPECT_TRUE(texture
->haveBackingTexture());
404 texture
->setTextureManager(0);
407 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
408 resourceManagerOne
->clearAllMemory(resourceProvider());
410 resourceManagerOne
.reset();
412 EXPECT_FALSE(texture
->canAcquireBackingTexture());
413 EXPECT_FALSE(texture
->haveBackingTexture());
415 texture
->setTextureManager(resourceManagerTwo
.get());
417 prioritizeTexturesAndBackings(resourceManagerTwo
.get());
419 EXPECT_TRUE(validateTexture(texture
, false));
420 EXPECT_TRUE(texture
->canAcquireBackingTexture());
421 EXPECT_TRUE(texture
->haveBackingTexture());
423 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
424 resourceManagerTwo
->clearAllMemory(resourceProvider());
427 TEST_F(PrioritizedResourceTest
, renderSurfacesReduceMemoryAvailableOutsideRootSurface
)
429 const size_t maxTextures
= 8;
430 scoped_ptr
<PrioritizedResourceManager
> resourceManager
= createManager(maxTextures
);
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(texturesMemorySize(4));
435 renderSurfacePlaceHolder
->setRequestPriority(PriorityCalculator::renderSurfacePriority());
437 // Create textures to fill our memory limit.
438 scoped_ptr
<PrioritizedResource
> textures
[maxTextures
];
440 for (size_t i
= 0; i
< maxTextures
; ++i
)
441 textures
[i
] = resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
443 // Set decreasing non-visible priorities outside root surface.
444 for (size_t i
= 0; i
< maxTextures
; ++i
)
445 textures
[i
]->setRequestPriority(100 + i
);
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));
454 // Set increasing non-visible priorities outside root surface.
455 for (size_t i
= 0; i
< maxTextures
; ++i
)
456 textures
[i
]->setRequestPriority(100 - i
);
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));
465 EXPECT_EQ(texturesMemorySize(4), resourceManager
->memoryAboveCutoffBytes());
466 EXPECT_EQ(texturesMemorySize(4), resourceManager
->memoryForSelfManagedTextures());
467 EXPECT_LE(resourceManager
->memoryUseBytes(), resourceManager
->memoryAboveCutoffBytes());
469 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
470 resourceManager
->clearAllMemory(resourceProvider());
473 TEST_F(PrioritizedResourceTest
, renderSurfacesReduceMemoryAvailableForRequestLate
)
475 const size_t maxTextures
= 8;
476 scoped_ptr
<PrioritizedResourceManager
> resourceManager
= createManager(maxTextures
);
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(texturesMemorySize(4));
481 renderSurfacePlaceHolder
->setRequestPriority(PriorityCalculator::renderSurfacePriority());
483 // Create textures to fill our memory limit.
484 scoped_ptr
<PrioritizedResource
> textures
[maxTextures
];
486 for (size_t i
= 0; i
< maxTextures
; ++i
)
487 textures
[i
] = resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
489 // Set equal priorities.
490 for (size_t i
= 0; i
< maxTextures
; ++i
)
491 textures
[i
]->setRequestPriority(100);
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));
502 EXPECT_EQ(texturesMemorySize(4), resourceManager
->memoryAboveCutoffBytes());
503 EXPECT_EQ(texturesMemorySize(4), resourceManager
->memoryForSelfManagedTextures());
504 EXPECT_LE(resourceManager
->memoryUseBytes(), resourceManager
->memoryAboveCutoffBytes());
506 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
507 resourceManager
->clearAllMemory(resourceProvider());
510 TEST_F(PrioritizedResourceTest
, whenRenderSurfaceNotAvailableTexturesAlsoNotAvailable
)
512 const size_t maxTextures
= 8;
513 scoped_ptr
<PrioritizedResourceManager
> resourceManager
= createManager(maxTextures
);
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(texturesMemorySize(4));
518 renderSurfacePlaceHolder
->setRequestPriority(PriorityCalculator::renderSurfacePriority());
520 // Create textures to fill our memory limit.
521 scoped_ptr
<PrioritizedResource
> textures
[maxTextures
];
523 for (size_t i
= 0; i
< maxTextures
; ++i
)
524 textures
[i
] = resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
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(false));
532 prioritizeTexturesAndBackings(resourceManager
.get());
534 // Unable to requestLate textures in the child surface.
535 EXPECT_FALSE(validateTexture(textures
[6], true));
536 EXPECT_FALSE(validateTexture(textures
[7], true));
538 // Root surface textures are valid.
539 for (size_t i
= 0; i
< 6; ++i
)
540 EXPECT_TRUE(validateTexture(textures
[i
], false));
542 EXPECT_EQ(texturesMemorySize(6), resourceManager
->memoryAboveCutoffBytes());
543 EXPECT_EQ(texturesMemorySize(2), resourceManager
->memoryForSelfManagedTextures());
544 EXPECT_LE(resourceManager
->memoryUseBytes(), resourceManager
->memoryAboveCutoffBytes());
546 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
547 resourceManager
->clearAllMemory(resourceProvider());
550 TEST_F(PrioritizedResourceTest
, requestLateBackingsSorting
)
552 const size_t maxTextures
= 8;
553 scoped_ptr
<PrioritizedResourceManager
> resourceManager
= createManager(maxTextures
);
554 resourceManager
->setMaxMemoryLimitBytes(texturesMemorySize(maxTextures
));
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_textureFormat
);
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));
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());
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());
577 // Push the priorities to the backings array and sort the backings array
578 resourceManagerUpdateBackingsPriorities(resourceManager
.get());
580 // Assert that the backings list be sorted with the below-limit backings
581 // before the above-limit backings.
582 resourceManagerAssertInvariants(resourceManager
.get());
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());
588 // Make sure that only the requestLate textures are above the priority cutoff
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()));
594 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
595 resourceManager
->clearAllMemory(resourceProvider());
598 TEST_F(PrioritizedResourceTest
, clearUploadsToEvictedResources
)
600 const size_t maxTextures
= 4;
601 scoped_ptr
<PrioritizedResourceManager
> resourceManager
=
602 createManager(maxTextures
);
603 resourceManager
->setMaxMemoryLimitBytes(texturesMemorySize(maxTextures
));
605 // Create textures to fill our memory limit.
606 scoped_ptr
<PrioritizedResource
> textures
[maxTextures
];
608 for (size_t i
= 0; i
< maxTextures
; ++i
)
609 textures
[i
] = resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
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));
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
);
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());
630 queue
.clearUploadsToEvictedResources();
631 EXPECT_EQ(4, queue
.fullUploadSize());
633 resourceManager
->reduceMemoryOnImplThread(
634 texturesMemorySize(1), PriorityCalculator::allowEverythingCutoff(), resourceProvider());
635 queue
.clearUploadsToEvictedResources();
636 EXPECT_EQ(1, queue
.fullUploadSize());
638 resourceManager
->reduceMemoryOnImplThread(0, PriorityCalculator::allowEverythingCutoff(), resourceProvider());
639 queue
.clearUploadsToEvictedResources();
640 EXPECT_EQ(0, queue
.fullUploadSize());
644 TEST_F(PrioritizedResourceTest
, usageStatistics
)
646 const size_t maxTextures
= 5;
647 scoped_ptr
<PrioritizedResourceManager
> resourceManager
= createManager(maxTextures
);
648 scoped_ptr
<PrioritizedResource
> textures
[maxTextures
];
650 for (size_t i
= 0; i
< maxTextures
; ++i
)
651 textures
[i
] = resourceManager
->createTexture(m_textureSize
, m_textureFormat
);
653 textures
[0]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff() - 1);
654 textures
[1]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff());
655 textures
[2]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff() - 1);
656 textures
[3]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff());
657 textures
[4]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff() + 1);
659 // Set max limit to 2 textures.
660 resourceManager
->setMaxMemoryLimitBytes(texturesMemorySize(2));
661 prioritizeTexturesAndBackings(resourceManager
.get());
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));
669 // Validate the statistics.
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
->memoryVisibleAndNearbyBytes());
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::allowVisibleAndNearbyCutoff() - 1);
682 textures
[4]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff());
683 resourceManager
->prioritizeTextures();
685 // Verify that we still see the old values.
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
->memoryVisibleAndNearbyBytes());
693 // Push priorities to backings, and verify we see the new values.
695 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&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
->memoryVisibleAndNearbyBytes());
702 DebugScopedSetImplThreadAndMainThreadBlocked
implThreadAndMainThreadBlocked(&m_proxy
);
703 resourceManager
->clearAllMemory(resourceProvider());