| Index: cc/tiles/gpu_image_decode_cache_unittest.cc
|
| diff --git a/cc/tiles/gpu_image_decode_cache_unittest.cc b/cc/tiles/gpu_image_decode_cache_unittest.cc
|
| index b1c73cf26380e82b53b3efa53e5bad80de483f0e..82ca3b207acc5010a73db38df5dbe2f901ff39a3 100644
|
| --- a/cc/tiles/gpu_image_decode_cache_unittest.cc
|
| +++ b/cc/tiles/gpu_image_decode_cache_unittest.cc
|
| @@ -19,6 +19,7 @@ class TestGpuImageDecodeCache : public GpuImageDecodeCache {
|
| explicit TestGpuImageDecodeCache(ContextProvider* context)
|
| : GpuImageDecodeCache(context,
|
| ResourceFormat::RGBA_8888,
|
| + kGpuMemoryLimitBytes,
|
| kGpuMemoryLimitBytes) {}
|
| };
|
|
|
| @@ -640,7 +641,7 @@ TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) {
|
| bool is_decomposable = true;
|
| SkFilterQuality quality = kHigh_SkFilterQuality;
|
|
|
| - cache.SetCachedBytesLimitForTesting(0);
|
| + cache.SetAllByteLimitsForTesting(0);
|
|
|
| sk_sp<SkImage> image = CreateImage(100, 100);
|
| DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
|
| @@ -861,7 +862,7 @@ TEST(GpuImageDecodeCacheTest, AtRasterUsedDirectlyIfSpaceAllows) {
|
| bool is_decomposable = true;
|
| SkFilterQuality quality = kHigh_SkFilterQuality;
|
|
|
| - cache.SetCachedBytesLimitForTesting(0);
|
| + cache.SetAllByteLimitsForTesting(0);
|
|
|
| sk_sp<SkImage> image = CreateImage(100, 100);
|
| DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
|
| @@ -884,7 +885,7 @@ TEST(GpuImageDecodeCacheTest, AtRasterUsedDirectlyIfSpaceAllows) {
|
| EXPECT_TRUE(decoded_draw_image.is_at_raster_decode());
|
| EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image));
|
|
|
| - cache.SetCachedBytesLimitForTesting(96 * 1024 * 1024);
|
| + cache.SetAllByteLimitsForTesting(96 * 1024 * 1024);
|
|
|
| // Finish our draw after increasing the memory limit, image should be added to
|
| // cache.
|
| @@ -906,7 +907,7 @@ TEST(GpuImageDecodeCacheTest,
|
| bool is_decomposable = true;
|
| SkFilterQuality quality = kHigh_SkFilterQuality;
|
|
|
| - cache.SetCachedBytesLimitForTesting(0);
|
| + cache.SetAllByteLimitsForTesting(0);
|
|
|
| sk_sp<SkImage> image = CreateImage(100, 100);
|
| DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
|
| @@ -1078,36 +1079,42 @@ TEST(GpuImageDecodeCacheTest, ShouldAggressivelyFreeResources) {
|
| cache.UnrefImage(draw_image);
|
|
|
| // We should now have data image in our cache.
|
| - DCHECK_GT(cache.GetBytesUsedForTesting(), 0u);
|
| + EXPECT_GT(cache.GetBytesUsedForTesting(), 0u);
|
|
|
| // Tell our cache to aggressively free resources.
|
| cache.SetShouldAggressivelyFreeResources(true);
|
| - DCHECK_EQ(0u, cache.GetBytesUsedForTesting());
|
| + EXPECT_EQ(0u, cache.GetBytesUsedForTesting());
|
|
|
| - // Attempting to upload a new image should result in at-raster decode.
|
| + // Attempting to upload a new image should succeed, but the image should not
|
| + // be cached past its use.
|
| {
|
| bool need_unref = cache.GetTaskForImageAndRef(
|
| draw_image, ImageDecodeCache::TracingInfo(), &task);
|
| - EXPECT_FALSE(need_unref);
|
| - EXPECT_FALSE(task);
|
| + EXPECT_TRUE(need_unref);
|
| + EXPECT_TRUE(task);
|
| +
|
| + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get());
|
| + TestTileTaskRunner::ProcessTask(task.get());
|
| + cache.UnrefImage(draw_image);
|
| +
|
| + EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u);
|
| }
|
|
|
| - // We now tell the cache to not aggressively free resources. Uploads
|
| - // should work again.
|
| + // We now tell the cache to not aggressively free resources. The image may
|
| + // now be cached past its use.
|
| cache.SetShouldAggressivelyFreeResources(false);
|
| {
|
| bool need_unref = cache.GetTaskForImageAndRef(
|
| draw_image, ImageDecodeCache::TracingInfo(), &task);
|
| EXPECT_TRUE(need_unref);
|
| EXPECT_TRUE(task);
|
| - }
|
|
|
| - TestTileTaskRunner::ProcessTask(task->dependencies()[0].get());
|
| - TestTileTaskRunner::ProcessTask(task.get());
|
| + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get());
|
| + TestTileTaskRunner::ProcessTask(task.get());
|
| + cache.UnrefImage(draw_image);
|
|
|
| - // The image should be in our cache after un-ref.
|
| - cache.UnrefImage(draw_image);
|
| - DCHECK_GT(cache.GetBytesUsedForTesting(), 0u);
|
| + EXPECT_GT(cache.GetBytesUsedForTesting(), 0u);
|
| + }
|
| }
|
|
|
| TEST(GpuImageDecodeCacheTest, OrphanedImagesFreeOnReachingZeroRefs) {
|
| @@ -1326,30 +1333,38 @@ TEST(GpuImageDecodeCacheTest, MemoryStateSuspended) {
|
| cache.UnrefImage(draw_image);
|
|
|
| // The image should be cached.
|
| - DCHECK_GT(cache.GetBytesUsedForTesting(), 0u);
|
| - DCHECK_EQ(cache.GetNumCacheEntriesForTesting(), 1u);
|
| + EXPECT_GT(cache.GetBytesUsedForTesting(), 0u);
|
| + EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 1u);
|
|
|
| // Set us to the not visible state (prerequisite for SUSPENDED).
|
| cache.SetShouldAggressivelyFreeResources(true);
|
|
|
| // Image should be cached, but not using memory budget.
|
| - DCHECK_EQ(cache.GetBytesUsedForTesting(), 0u);
|
| - DCHECK_EQ(cache.GetNumCacheEntriesForTesting(), 1u);
|
| + EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u);
|
| + EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 1u);
|
|
|
| // Set us to the SUSPENDED state with purging.
|
| cache.OnPurgeMemory();
|
| cache.OnMemoryStateChange(base::MemoryState::SUSPENDED);
|
|
|
| // Nothing should be cached.
|
| - DCHECK_EQ(cache.GetBytesUsedForTesting(), 0u);
|
| - DCHECK_EQ(cache.GetNumCacheEntriesForTesting(), 0u);
|
| + EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u);
|
| + EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 0u);
|
|
|
| - // Attempts to get a task for the image should fail, as we have no space (at
|
| - // raster only).
|
| + // Attempts to get a task for the image will still succeed, as SUSPENDED
|
| + // doesn't impact working set size.
|
| need_unref = cache.GetTaskForImageAndRef(
|
| draw_image, ImageDecodeCache::TracingInfo(), &task);
|
| - EXPECT_FALSE(need_unref);
|
| - EXPECT_FALSE(task);
|
| + EXPECT_TRUE(need_unref);
|
| + EXPECT_TRUE(task);
|
| +
|
| + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get());
|
| + TestTileTaskRunner::ProcessTask(task.get());
|
| + cache.UnrefImage(draw_image);
|
| +
|
| + // Nothing should be cached.
|
| + EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u);
|
| + EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 0u);
|
|
|
| // Restore us to visible and NORMAL memory state.
|
| cache.OnMemoryStateChange(base::MemoryState::NORMAL);
|
| @@ -1392,5 +1407,150 @@ TEST(GpuImageDecodeCacheTest, OutOfRasterDecodeTask) {
|
| cache.UnrefImage(draw_image);
|
| }
|
|
|
| +TEST(GpuImageDecodeCacheTest, ZeroCacheNormalWorkingSet) {
|
| + // Setup - Image cache has a normal working set, but zero cache size.
|
| + auto context_provider = TestContextProvider::Create();
|
| + context_provider->BindToCurrentThread();
|
| + GpuImageDecodeCache cache(context_provider.get(), ResourceFormat::RGBA_8888,
|
| + kGpuMemoryLimitBytes, 0);
|
| + bool is_decomposable = true;
|
| + SkFilterQuality quality = kHigh_SkFilterQuality;
|
| +
|
| + // Add an image to the cache. Due to normal working set, this should produce
|
| + // a task and a ref.
|
| + sk_sp<SkImage> image = CreateImage(100, 100);
|
| + DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
|
| + quality,
|
| + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable));
|
| + scoped_refptr<TileTask> task;
|
| + bool need_unref = cache.GetTaskForImageAndRef(
|
| + draw_image, ImageDecodeCache::TracingInfo(), &task);
|
| + EXPECT_TRUE(need_unref);
|
| + EXPECT_TRUE(task);
|
| + EXPECT_EQ(task->dependencies().size(), 1u);
|
| + EXPECT_TRUE(task->dependencies()[0]);
|
| +
|
| + // Run the task.
|
| + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get());
|
| + TestTileTaskRunner::ProcessTask(task.get());
|
| +
|
| + // Request the same image - it should be cached.
|
| + scoped_refptr<TileTask> task2;
|
| + need_unref = cache.GetTaskForImageAndRef(
|
| + draw_image, ImageDecodeCache::TracingInfo(), &task2);
|
| + EXPECT_TRUE(need_unref);
|
| + EXPECT_FALSE(task2);
|
| +
|
| + // Unref both images.
|
| + cache.UnrefImage(draw_image);
|
| + cache.UnrefImage(draw_image);
|
| +
|
| + // Get the image again. As it was fully unreffed, it is no longer in the
|
| + // working set and will be evicted due to 0 cache size.
|
| + scoped_refptr<TileTask> task3;
|
| + need_unref = cache.GetTaskForImageAndRef(
|
| + draw_image, ImageDecodeCache::TracingInfo(), &task3);
|
| + EXPECT_TRUE(need_unref);
|
| + EXPECT_TRUE(task3);
|
| + EXPECT_EQ(task3->dependencies().size(), 1u);
|
| + EXPECT_TRUE(task->dependencies()[0]);
|
| +
|
| + TestTileTaskRunner::ProcessTask(task3->dependencies()[0].get());
|
| + TestTileTaskRunner::ProcessTask(task3.get());
|
| +
|
| + cache.UnrefImage(draw_image);
|
| +}
|
| +
|
| +TEST(GpuImageDecodeCacheTest, SmallCacheNormalWorkingSet) {
|
| + // Cache will fit one (but not two) 100x100 images.
|
| + size_t cache_size = 190 * 100 * 4;
|
| +
|
| + auto context_provider = TestContextProvider::Create();
|
| + context_provider->BindToCurrentThread();
|
| + GpuImageDecodeCache cache(context_provider.get(), ResourceFormat::RGBA_8888,
|
| + kGpuMemoryLimitBytes, cache_size);
|
| + bool is_decomposable = true;
|
| + SkFilterQuality quality = kHigh_SkFilterQuality;
|
| +
|
| + sk_sp<SkImage> image = CreateImage(100, 100);
|
| + DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()),
|
| + quality,
|
| + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable));
|
| +
|
| + sk_sp<SkImage> image2 = CreateImage(100, 100);
|
| + DrawImage draw_image2(
|
| + image2, SkIRect::MakeWH(image2->width(), image2->height()), quality,
|
| + CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable));
|
| +
|
| + // Add an image to the cache and un-ref it.
|
| + {
|
| + scoped_refptr<TileTask> task;
|
| + bool need_unref = cache.GetTaskForImageAndRef(
|
| + draw_image, ImageDecodeCache::TracingInfo(), &task);
|
| + EXPECT_TRUE(need_unref);
|
| + EXPECT_TRUE(task);
|
| + EXPECT_EQ(task->dependencies().size(), 1u);
|
| + EXPECT_TRUE(task->dependencies()[0]);
|
| +
|
| + // Run the task and unref the image.
|
| + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get());
|
| + TestTileTaskRunner::ProcessTask(task.get());
|
| + cache.UnrefImage(draw_image);
|
| + }
|
| +
|
| + // Request the same image - it should be cached.
|
| + {
|
| + scoped_refptr<TileTask> task;
|
| + bool need_unref = cache.GetTaskForImageAndRef(
|
| + draw_image, ImageDecodeCache::TracingInfo(), &task);
|
| + EXPECT_TRUE(need_unref);
|
| + EXPECT_FALSE(task);
|
| + cache.UnrefImage(draw_image);
|
| + }
|
| +
|
| + // Add a new image to the cache. It should push out the old one.
|
| + {
|
| + scoped_refptr<TileTask> task;
|
| + bool need_unref = cache.GetTaskForImageAndRef(
|
| + draw_image2, ImageDecodeCache::TracingInfo(), &task);
|
| + EXPECT_TRUE(need_unref);
|
| + EXPECT_TRUE(task);
|
| + EXPECT_EQ(task->dependencies().size(), 1u);
|
| + EXPECT_TRUE(task->dependencies()[0]);
|
| +
|
| + // Run the task and unref the image.
|
| + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get());
|
| + TestTileTaskRunner::ProcessTask(task.get());
|
| + cache.UnrefImage(draw_image2);
|
| + }
|
| +
|
| + // Request the second image - it should be cached.
|
| + {
|
| + scoped_refptr<TileTask> task;
|
| + bool need_unref = cache.GetTaskForImageAndRef(
|
| + draw_image2, ImageDecodeCache::TracingInfo(), &task);
|
| + EXPECT_TRUE(need_unref);
|
| + EXPECT_FALSE(task);
|
| + cache.UnrefImage(draw_image2);
|
| + }
|
| +
|
| + // Request the first image - it should have been evicted and return a new
|
| + // task.
|
| + {
|
| + scoped_refptr<TileTask> task;
|
| + bool need_unref = cache.GetTaskForImageAndRef(
|
| + draw_image, ImageDecodeCache::TracingInfo(), &task);
|
| + EXPECT_TRUE(need_unref);
|
| + EXPECT_TRUE(task);
|
| + EXPECT_EQ(task->dependencies().size(), 1u);
|
| + EXPECT_TRUE(task->dependencies()[0]);
|
| +
|
| + // Run the task and unref the image.
|
| + TestTileTaskRunner::ProcessTask(task->dependencies()[0].get());
|
| + TestTileTaskRunner::ProcessTask(task.get());
|
| + cache.UnrefImage(draw_image);
|
| + }
|
| +}
|
| +
|
| } // namespace
|
| } // namespace cc
|
|
|