| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/tiles/gpu_image_decode_cache.h" | 5 #include "cc/tiles/gpu_image_decode_cache.h" |
| 6 | 6 |
| 7 #include "cc/paint/draw_image.h" | 7 #include "cc/paint/draw_image.h" |
| 8 #include "cc/test/test_context_provider.h" | 8 #include "cc/test/test_context_provider.h" |
| 9 #include "cc/test/test_tile_task_runner.h" | 9 #include "cc/test/test_tile_task_runner.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
| 11 #include "third_party/skia/include/core/SkRefCnt.h" | 11 #include "third_party/skia/include/core/SkRefCnt.h" |
| 12 | 12 |
| 13 namespace cc { | 13 namespace cc { |
| 14 namespace { | 14 namespace { |
| 15 | 15 |
| 16 size_t kGpuMemoryLimitBytes = 96 * 1024 * 1024; | 16 size_t kGpuMemoryLimitBytes = 96 * 1024 * 1024; |
| 17 class TestGpuImageDecodeCache : public GpuImageDecodeCache { | 17 class TestGpuImageDecodeCache : public GpuImageDecodeCache { |
| 18 public: | 18 public: |
| 19 explicit TestGpuImageDecodeCache(ContextProvider* context) | 19 explicit TestGpuImageDecodeCache(ContextProvider* context) |
| 20 : GpuImageDecodeCache(context, | 20 : GpuImageDecodeCache(context, |
| 21 ResourceFormat::RGBA_8888, | 21 ResourceFormat::RGBA_8888, |
| 22 kGpuMemoryLimitBytes, |
| 22 kGpuMemoryLimitBytes) {} | 23 kGpuMemoryLimitBytes) {} |
| 23 }; | 24 }; |
| 24 | 25 |
| 25 sk_sp<SkImage> CreateImage(int width, int height) { | 26 sk_sp<SkImage> CreateImage(int width, int height) { |
| 26 SkBitmap bitmap; | 27 SkBitmap bitmap; |
| 27 bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height)); | 28 bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height)); |
| 28 return SkImage::MakeFromBitmap(bitmap); | 29 return SkImage::MakeFromBitmap(bitmap); |
| 29 } | 30 } |
| 30 | 31 |
| 31 SkMatrix CreateMatrix(const SkSize& scale, bool is_decomposable) { | 32 SkMatrix CreateMatrix(const SkSize& scale, bool is_decomposable) { |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image)); | 634 EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image)); |
| 634 } | 635 } |
| 635 | 636 |
| 636 TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) { | 637 TEST(GpuImageDecodeCacheTest, GetDecodedImageForDrawAtRasterDecode) { |
| 637 auto context_provider = TestContextProvider::Create(); | 638 auto context_provider = TestContextProvider::Create(); |
| 638 context_provider->BindToCurrentThread(); | 639 context_provider->BindToCurrentThread(); |
| 639 TestGpuImageDecodeCache cache(context_provider.get()); | 640 TestGpuImageDecodeCache cache(context_provider.get()); |
| 640 bool is_decomposable = true; | 641 bool is_decomposable = true; |
| 641 SkFilterQuality quality = kHigh_SkFilterQuality; | 642 SkFilterQuality quality = kHigh_SkFilterQuality; |
| 642 | 643 |
| 643 cache.SetCachedBytesLimitForTesting(0); | 644 cache.SetAllByteLimitsForTesting(0); |
| 644 | 645 |
| 645 sk_sp<SkImage> image = CreateImage(100, 100); | 646 sk_sp<SkImage> image = CreateImage(100, 100); |
| 646 DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), | 647 DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), |
| 647 quality, | 648 quality, |
| 648 CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); | 649 CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); |
| 649 | 650 |
| 650 scoped_refptr<TileTask> task; | 651 scoped_refptr<TileTask> task; |
| 651 bool need_unref = cache.GetTaskForImageAndRef( | 652 bool need_unref = cache.GetTaskForImageAndRef( |
| 652 draw_image, ImageDecodeCache::TracingInfo(), &task); | 653 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 653 EXPECT_FALSE(need_unref); | 654 EXPECT_FALSE(need_unref); |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image)); | 855 EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image)); |
| 855 } | 856 } |
| 856 | 857 |
| 857 TEST(GpuImageDecodeCacheTest, AtRasterUsedDirectlyIfSpaceAllows) { | 858 TEST(GpuImageDecodeCacheTest, AtRasterUsedDirectlyIfSpaceAllows) { |
| 858 auto context_provider = TestContextProvider::Create(); | 859 auto context_provider = TestContextProvider::Create(); |
| 859 context_provider->BindToCurrentThread(); | 860 context_provider->BindToCurrentThread(); |
| 860 TestGpuImageDecodeCache cache(context_provider.get()); | 861 TestGpuImageDecodeCache cache(context_provider.get()); |
| 861 bool is_decomposable = true; | 862 bool is_decomposable = true; |
| 862 SkFilterQuality quality = kHigh_SkFilterQuality; | 863 SkFilterQuality quality = kHigh_SkFilterQuality; |
| 863 | 864 |
| 864 cache.SetCachedBytesLimitForTesting(0); | 865 cache.SetAllByteLimitsForTesting(0); |
| 865 | 866 |
| 866 sk_sp<SkImage> image = CreateImage(100, 100); | 867 sk_sp<SkImage> image = CreateImage(100, 100); |
| 867 DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), | 868 DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), |
| 868 quality, | 869 quality, |
| 869 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); | 870 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); |
| 870 | 871 |
| 871 scoped_refptr<TileTask> task; | 872 scoped_refptr<TileTask> task; |
| 872 bool need_unref = cache.GetTaskForImageAndRef( | 873 bool need_unref = cache.GetTaskForImageAndRef( |
| 873 draw_image, ImageDecodeCache::TracingInfo(), &task); | 874 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 874 EXPECT_FALSE(need_unref); | 875 EXPECT_FALSE(need_unref); |
| 875 EXPECT_FALSE(task); | 876 EXPECT_FALSE(task); |
| 876 | 877 |
| 877 // Must hold context lock before calling GetDecodedImageForDraw / | 878 // Must hold context lock before calling GetDecodedImageForDraw / |
| 878 // DrawWithImageFinished. | 879 // DrawWithImageFinished. |
| 879 ContextProvider::ScopedContextLock context_lock(context_provider.get()); | 880 ContextProvider::ScopedContextLock context_lock(context_provider.get()); |
| 880 DecodedDrawImage decoded_draw_image = | 881 DecodedDrawImage decoded_draw_image = |
| 881 cache.GetDecodedImageForDraw(draw_image); | 882 cache.GetDecodedImageForDraw(draw_image); |
| 882 EXPECT_TRUE(decoded_draw_image.image()); | 883 EXPECT_TRUE(decoded_draw_image.image()); |
| 883 EXPECT_TRUE(decoded_draw_image.image()->isTextureBacked()); | 884 EXPECT_TRUE(decoded_draw_image.image()->isTextureBacked()); |
| 884 EXPECT_TRUE(decoded_draw_image.is_at_raster_decode()); | 885 EXPECT_TRUE(decoded_draw_image.is_at_raster_decode()); |
| 885 EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image)); | 886 EXPECT_FALSE(cache.DiscardableIsLockedForTesting(draw_image)); |
| 886 | 887 |
| 887 cache.SetCachedBytesLimitForTesting(96 * 1024 * 1024); | 888 cache.SetAllByteLimitsForTesting(96 * 1024 * 1024); |
| 888 | 889 |
| 889 // Finish our draw after increasing the memory limit, image should be added to | 890 // Finish our draw after increasing the memory limit, image should be added to |
| 890 // cache. | 891 // cache. |
| 891 cache.DrawWithImageFinished(draw_image, decoded_draw_image); | 892 cache.DrawWithImageFinished(draw_image, decoded_draw_image); |
| 892 | 893 |
| 893 scoped_refptr<TileTask> another_task; | 894 scoped_refptr<TileTask> another_task; |
| 894 bool another_task_needs_unref = cache.GetTaskForImageAndRef( | 895 bool another_task_needs_unref = cache.GetTaskForImageAndRef( |
| 895 draw_image, ImageDecodeCache::TracingInfo(), &task); | 896 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 896 EXPECT_TRUE(another_task_needs_unref); | 897 EXPECT_TRUE(another_task_needs_unref); |
| 897 EXPECT_FALSE(another_task); | 898 EXPECT_FALSE(another_task); |
| 898 cache.UnrefImage(draw_image); | 899 cache.UnrefImage(draw_image); |
| 899 } | 900 } |
| 900 | 901 |
| 901 TEST(GpuImageDecodeCacheTest, | 902 TEST(GpuImageDecodeCacheTest, |
| 902 GetDecodedImageForDrawAtRasterDecodeMultipleTimes) { | 903 GetDecodedImageForDrawAtRasterDecodeMultipleTimes) { |
| 903 auto context_provider = TestContextProvider::Create(); | 904 auto context_provider = TestContextProvider::Create(); |
| 904 context_provider->BindToCurrentThread(); | 905 context_provider->BindToCurrentThread(); |
| 905 TestGpuImageDecodeCache cache(context_provider.get()); | 906 TestGpuImageDecodeCache cache(context_provider.get()); |
| 906 bool is_decomposable = true; | 907 bool is_decomposable = true; |
| 907 SkFilterQuality quality = kHigh_SkFilterQuality; | 908 SkFilterQuality quality = kHigh_SkFilterQuality; |
| 908 | 909 |
| 909 cache.SetCachedBytesLimitForTesting(0); | 910 cache.SetAllByteLimitsForTesting(0); |
| 910 | 911 |
| 911 sk_sp<SkImage> image = CreateImage(100, 100); | 912 sk_sp<SkImage> image = CreateImage(100, 100); |
| 912 DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), | 913 DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), |
| 913 quality, | 914 quality, |
| 914 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); | 915 CreateMatrix(SkSize::Make(0.5f, 0.5f), is_decomposable)); |
| 915 | 916 |
| 916 // Must hold context lock before calling GetDecodedImageForDraw / | 917 // Must hold context lock before calling GetDecodedImageForDraw / |
| 917 // DrawWithImageFinished. | 918 // DrawWithImageFinished. |
| 918 ContextProvider::ScopedContextLock context_lock(context_provider.get()); | 919 ContextProvider::ScopedContextLock context_lock(context_provider.get()); |
| 919 DecodedDrawImage decoded_draw_image = | 920 DecodedDrawImage decoded_draw_image = |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1071 EXPECT_TRUE(need_unref); | 1072 EXPECT_TRUE(need_unref); |
| 1072 EXPECT_TRUE(task); | 1073 EXPECT_TRUE(task); |
| 1073 } | 1074 } |
| 1074 | 1075 |
| 1075 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); | 1076 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); |
| 1076 TestTileTaskRunner::ProcessTask(task.get()); | 1077 TestTileTaskRunner::ProcessTask(task.get()); |
| 1077 | 1078 |
| 1078 cache.UnrefImage(draw_image); | 1079 cache.UnrefImage(draw_image); |
| 1079 | 1080 |
| 1080 // We should now have data image in our cache. | 1081 // We should now have data image in our cache. |
| 1081 DCHECK_GT(cache.GetBytesUsedForTesting(), 0u); | 1082 EXPECT_GT(cache.GetBytesUsedForTesting(), 0u); |
| 1082 | 1083 |
| 1083 // Tell our cache to aggressively free resources. | 1084 // Tell our cache to aggressively free resources. |
| 1084 cache.SetShouldAggressivelyFreeResources(true); | 1085 cache.SetShouldAggressivelyFreeResources(true); |
| 1085 DCHECK_EQ(0u, cache.GetBytesUsedForTesting()); | 1086 EXPECT_EQ(0u, cache.GetBytesUsedForTesting()); |
| 1086 | 1087 |
| 1087 // Attempting to upload a new image should result in at-raster decode. | 1088 // Attempting to upload a new image should succeed, but the image should not |
| 1089 // be cached past its use. |
| 1088 { | 1090 { |
| 1089 bool need_unref = cache.GetTaskForImageAndRef( | 1091 bool need_unref = cache.GetTaskForImageAndRef( |
| 1090 draw_image, ImageDecodeCache::TracingInfo(), &task); | 1092 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 1091 EXPECT_FALSE(need_unref); | 1093 EXPECT_TRUE(need_unref); |
| 1092 EXPECT_FALSE(task); | 1094 EXPECT_TRUE(task); |
| 1095 |
| 1096 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); |
| 1097 TestTileTaskRunner::ProcessTask(task.get()); |
| 1098 cache.UnrefImage(draw_image); |
| 1099 |
| 1100 EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u); |
| 1093 } | 1101 } |
| 1094 | 1102 |
| 1095 // We now tell the cache to not aggressively free resources. Uploads | 1103 // We now tell the cache to not aggressively free resources. The image may |
| 1096 // should work again. | 1104 // now be cached past its use. |
| 1097 cache.SetShouldAggressivelyFreeResources(false); | 1105 cache.SetShouldAggressivelyFreeResources(false); |
| 1098 { | 1106 { |
| 1099 bool need_unref = cache.GetTaskForImageAndRef( | 1107 bool need_unref = cache.GetTaskForImageAndRef( |
| 1100 draw_image, ImageDecodeCache::TracingInfo(), &task); | 1108 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 1101 EXPECT_TRUE(need_unref); | 1109 EXPECT_TRUE(need_unref); |
| 1102 EXPECT_TRUE(task); | 1110 EXPECT_TRUE(task); |
| 1111 |
| 1112 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); |
| 1113 TestTileTaskRunner::ProcessTask(task.get()); |
| 1114 cache.UnrefImage(draw_image); |
| 1115 |
| 1116 EXPECT_GT(cache.GetBytesUsedForTesting(), 0u); |
| 1103 } | 1117 } |
| 1104 | |
| 1105 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); | |
| 1106 TestTileTaskRunner::ProcessTask(task.get()); | |
| 1107 | |
| 1108 // The image should be in our cache after un-ref. | |
| 1109 cache.UnrefImage(draw_image); | |
| 1110 DCHECK_GT(cache.GetBytesUsedForTesting(), 0u); | |
| 1111 } | 1118 } |
| 1112 | 1119 |
| 1113 TEST(GpuImageDecodeCacheTest, OrphanedImagesFreeOnReachingZeroRefs) { | 1120 TEST(GpuImageDecodeCacheTest, OrphanedImagesFreeOnReachingZeroRefs) { |
| 1114 auto context_provider = TestContextProvider::Create(); | 1121 auto context_provider = TestContextProvider::Create(); |
| 1115 context_provider->BindToCurrentThread(); | 1122 context_provider->BindToCurrentThread(); |
| 1116 TestGpuImageDecodeCache cache(context_provider.get()); | 1123 TestGpuImageDecodeCache cache(context_provider.get()); |
| 1117 bool is_decomposable = true; | 1124 bool is_decomposable = true; |
| 1118 SkFilterQuality quality = kHigh_SkFilterQuality; | 1125 SkFilterQuality quality = kHigh_SkFilterQuality; |
| 1119 | 1126 |
| 1120 // Create a downscaled image. | 1127 // Create a downscaled image. |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1319 bool need_unref = cache.GetTaskForImageAndRef( | 1326 bool need_unref = cache.GetTaskForImageAndRef( |
| 1320 draw_image, ImageDecodeCache::TracingInfo(), &task); | 1327 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 1321 EXPECT_TRUE(need_unref); | 1328 EXPECT_TRUE(need_unref); |
| 1322 EXPECT_TRUE(task); | 1329 EXPECT_TRUE(task); |
| 1323 | 1330 |
| 1324 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); | 1331 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); |
| 1325 TestTileTaskRunner::ProcessTask(task.get()); | 1332 TestTileTaskRunner::ProcessTask(task.get()); |
| 1326 cache.UnrefImage(draw_image); | 1333 cache.UnrefImage(draw_image); |
| 1327 | 1334 |
| 1328 // The image should be cached. | 1335 // The image should be cached. |
| 1329 DCHECK_GT(cache.GetBytesUsedForTesting(), 0u); | 1336 EXPECT_GT(cache.GetBytesUsedForTesting(), 0u); |
| 1330 DCHECK_EQ(cache.GetNumCacheEntriesForTesting(), 1u); | 1337 EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 1u); |
| 1331 | 1338 |
| 1332 // Set us to the not visible state (prerequisite for SUSPENDED). | 1339 // Set us to the not visible state (prerequisite for SUSPENDED). |
| 1333 cache.SetShouldAggressivelyFreeResources(true); | 1340 cache.SetShouldAggressivelyFreeResources(true); |
| 1334 | 1341 |
| 1335 // Image should be cached, but not using memory budget. | 1342 // Image should be cached, but not using memory budget. |
| 1336 DCHECK_EQ(cache.GetBytesUsedForTesting(), 0u); | 1343 EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u); |
| 1337 DCHECK_EQ(cache.GetNumCacheEntriesForTesting(), 1u); | 1344 EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 1u); |
| 1338 | 1345 |
| 1339 // Set us to the SUSPENDED state with purging. | 1346 // Set us to the SUSPENDED state with purging. |
| 1340 cache.OnPurgeMemory(); | 1347 cache.OnPurgeMemory(); |
| 1341 cache.OnMemoryStateChange(base::MemoryState::SUSPENDED); | 1348 cache.OnMemoryStateChange(base::MemoryState::SUSPENDED); |
| 1342 | 1349 |
| 1343 // Nothing should be cached. | 1350 // Nothing should be cached. |
| 1344 DCHECK_EQ(cache.GetBytesUsedForTesting(), 0u); | 1351 EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u); |
| 1345 DCHECK_EQ(cache.GetNumCacheEntriesForTesting(), 0u); | 1352 EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 0u); |
| 1346 | 1353 |
| 1347 // Attempts to get a task for the image should fail, as we have no space (at | 1354 // Attempts to get a task for the image will still succeed, as SUSPENDED |
| 1348 // raster only). | 1355 // doesn't impact working set size. |
| 1349 need_unref = cache.GetTaskForImageAndRef( | 1356 need_unref = cache.GetTaskForImageAndRef( |
| 1350 draw_image, ImageDecodeCache::TracingInfo(), &task); | 1357 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 1351 EXPECT_FALSE(need_unref); | 1358 EXPECT_TRUE(need_unref); |
| 1352 EXPECT_FALSE(task); | 1359 EXPECT_TRUE(task); |
| 1360 |
| 1361 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); |
| 1362 TestTileTaskRunner::ProcessTask(task.get()); |
| 1363 cache.UnrefImage(draw_image); |
| 1364 |
| 1365 // Nothing should be cached. |
| 1366 EXPECT_EQ(cache.GetBytesUsedForTesting(), 0u); |
| 1367 EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 0u); |
| 1353 | 1368 |
| 1354 // Restore us to visible and NORMAL memory state. | 1369 // Restore us to visible and NORMAL memory state. |
| 1355 cache.OnMemoryStateChange(base::MemoryState::NORMAL); | 1370 cache.OnMemoryStateChange(base::MemoryState::NORMAL); |
| 1356 cache.SetShouldAggressivelyFreeResources(false); | 1371 cache.SetShouldAggressivelyFreeResources(false); |
| 1357 | 1372 |
| 1358 // We should now be able to create a task again (space available). | 1373 // We should now be able to create a task again (space available). |
| 1359 need_unref = cache.GetTaskForImageAndRef( | 1374 need_unref = cache.GetTaskForImageAndRef( |
| 1360 draw_image, ImageDecodeCache::TracingInfo(), &task); | 1375 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 1361 EXPECT_TRUE(need_unref); | 1376 EXPECT_TRUE(need_unref); |
| 1362 EXPECT_TRUE(task); | 1377 EXPECT_TRUE(task); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1385 EXPECT_TRUE(cache.IsInInUseCacheForTesting(draw_image)); | 1400 EXPECT_TRUE(cache.IsInInUseCacheForTesting(draw_image)); |
| 1386 | 1401 |
| 1387 // Run the decode task. | 1402 // Run the decode task. |
| 1388 TestTileTaskRunner::ProcessTask(task.get()); | 1403 TestTileTaskRunner::ProcessTask(task.get()); |
| 1389 | 1404 |
| 1390 // The image should remain in the cache till we unref it. | 1405 // The image should remain in the cache till we unref it. |
| 1391 EXPECT_TRUE(cache.IsInInUseCacheForTesting(draw_image)); | 1406 EXPECT_TRUE(cache.IsInInUseCacheForTesting(draw_image)); |
| 1392 cache.UnrefImage(draw_image); | 1407 cache.UnrefImage(draw_image); |
| 1393 } | 1408 } |
| 1394 | 1409 |
| 1410 TEST(GpuImageDecodeCacheTest, ZeroCacheNormalWorkingSet) { |
| 1411 // Setup - Image cache has a normal working set, but zero cache size. |
| 1412 auto context_provider = TestContextProvider::Create(); |
| 1413 context_provider->BindToCurrentThread(); |
| 1414 GpuImageDecodeCache cache(context_provider.get(), ResourceFormat::RGBA_8888, |
| 1415 kGpuMemoryLimitBytes, 0); |
| 1416 bool is_decomposable = true; |
| 1417 SkFilterQuality quality = kHigh_SkFilterQuality; |
| 1418 |
| 1419 // Add an image to the cache. Due to normal working set, this should produce |
| 1420 // a task and a ref. |
| 1421 sk_sp<SkImage> image = CreateImage(100, 100); |
| 1422 DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), |
| 1423 quality, |
| 1424 CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); |
| 1425 scoped_refptr<TileTask> task; |
| 1426 bool need_unref = cache.GetTaskForImageAndRef( |
| 1427 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 1428 EXPECT_TRUE(need_unref); |
| 1429 EXPECT_TRUE(task); |
| 1430 EXPECT_EQ(task->dependencies().size(), 1u); |
| 1431 EXPECT_TRUE(task->dependencies()[0]); |
| 1432 |
| 1433 // Run the task. |
| 1434 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); |
| 1435 TestTileTaskRunner::ProcessTask(task.get()); |
| 1436 |
| 1437 // Request the same image - it should be cached. |
| 1438 scoped_refptr<TileTask> task2; |
| 1439 need_unref = cache.GetTaskForImageAndRef( |
| 1440 draw_image, ImageDecodeCache::TracingInfo(), &task2); |
| 1441 EXPECT_TRUE(need_unref); |
| 1442 EXPECT_FALSE(task2); |
| 1443 |
| 1444 // Unref both images. |
| 1445 cache.UnrefImage(draw_image); |
| 1446 cache.UnrefImage(draw_image); |
| 1447 |
| 1448 // Get the image again. As it was fully unreffed, it is no longer in the |
| 1449 // working set and will be evicted due to 0 cache size. |
| 1450 scoped_refptr<TileTask> task3; |
| 1451 need_unref = cache.GetTaskForImageAndRef( |
| 1452 draw_image, ImageDecodeCache::TracingInfo(), &task3); |
| 1453 EXPECT_TRUE(need_unref); |
| 1454 EXPECT_TRUE(task3); |
| 1455 EXPECT_EQ(task3->dependencies().size(), 1u); |
| 1456 EXPECT_TRUE(task->dependencies()[0]); |
| 1457 |
| 1458 TestTileTaskRunner::ProcessTask(task3->dependencies()[0].get()); |
| 1459 TestTileTaskRunner::ProcessTask(task3.get()); |
| 1460 |
| 1461 cache.UnrefImage(draw_image); |
| 1462 } |
| 1463 |
| 1464 TEST(GpuImageDecodeCacheTest, SmallCacheNormalWorkingSet) { |
| 1465 // Cache will fit one (but not two) 100x100 images. |
| 1466 size_t cache_size = 190 * 100 * 4; |
| 1467 |
| 1468 auto context_provider = TestContextProvider::Create(); |
| 1469 context_provider->BindToCurrentThread(); |
| 1470 GpuImageDecodeCache cache(context_provider.get(), ResourceFormat::RGBA_8888, |
| 1471 kGpuMemoryLimitBytes, cache_size); |
| 1472 bool is_decomposable = true; |
| 1473 SkFilterQuality quality = kHigh_SkFilterQuality; |
| 1474 |
| 1475 sk_sp<SkImage> image = CreateImage(100, 100); |
| 1476 DrawImage draw_image(image, SkIRect::MakeWH(image->width(), image->height()), |
| 1477 quality, |
| 1478 CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); |
| 1479 |
| 1480 sk_sp<SkImage> image2 = CreateImage(100, 100); |
| 1481 DrawImage draw_image2( |
| 1482 image2, SkIRect::MakeWH(image2->width(), image2->height()), quality, |
| 1483 CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable)); |
| 1484 |
| 1485 // Add an image to the cache and un-ref it. |
| 1486 { |
| 1487 scoped_refptr<TileTask> task; |
| 1488 bool need_unref = cache.GetTaskForImageAndRef( |
| 1489 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 1490 EXPECT_TRUE(need_unref); |
| 1491 EXPECT_TRUE(task); |
| 1492 EXPECT_EQ(task->dependencies().size(), 1u); |
| 1493 EXPECT_TRUE(task->dependencies()[0]); |
| 1494 |
| 1495 // Run the task and unref the image. |
| 1496 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); |
| 1497 TestTileTaskRunner::ProcessTask(task.get()); |
| 1498 cache.UnrefImage(draw_image); |
| 1499 } |
| 1500 |
| 1501 // Request the same image - it should be cached. |
| 1502 { |
| 1503 scoped_refptr<TileTask> task; |
| 1504 bool need_unref = cache.GetTaskForImageAndRef( |
| 1505 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 1506 EXPECT_TRUE(need_unref); |
| 1507 EXPECT_FALSE(task); |
| 1508 cache.UnrefImage(draw_image); |
| 1509 } |
| 1510 |
| 1511 // Add a new image to the cache. It should push out the old one. |
| 1512 { |
| 1513 scoped_refptr<TileTask> task; |
| 1514 bool need_unref = cache.GetTaskForImageAndRef( |
| 1515 draw_image2, ImageDecodeCache::TracingInfo(), &task); |
| 1516 EXPECT_TRUE(need_unref); |
| 1517 EXPECT_TRUE(task); |
| 1518 EXPECT_EQ(task->dependencies().size(), 1u); |
| 1519 EXPECT_TRUE(task->dependencies()[0]); |
| 1520 |
| 1521 // Run the task and unref the image. |
| 1522 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); |
| 1523 TestTileTaskRunner::ProcessTask(task.get()); |
| 1524 cache.UnrefImage(draw_image2); |
| 1525 } |
| 1526 |
| 1527 // Request the second image - it should be cached. |
| 1528 { |
| 1529 scoped_refptr<TileTask> task; |
| 1530 bool need_unref = cache.GetTaskForImageAndRef( |
| 1531 draw_image2, ImageDecodeCache::TracingInfo(), &task); |
| 1532 EXPECT_TRUE(need_unref); |
| 1533 EXPECT_FALSE(task); |
| 1534 cache.UnrefImage(draw_image2); |
| 1535 } |
| 1536 |
| 1537 // Request the first image - it should have been evicted and return a new |
| 1538 // task. |
| 1539 { |
| 1540 scoped_refptr<TileTask> task; |
| 1541 bool need_unref = cache.GetTaskForImageAndRef( |
| 1542 draw_image, ImageDecodeCache::TracingInfo(), &task); |
| 1543 EXPECT_TRUE(need_unref); |
| 1544 EXPECT_TRUE(task); |
| 1545 EXPECT_EQ(task->dependencies().size(), 1u); |
| 1546 EXPECT_TRUE(task->dependencies()[0]); |
| 1547 |
| 1548 // Run the task and unref the image. |
| 1549 TestTileTaskRunner::ProcessTask(task->dependencies()[0].get()); |
| 1550 TestTileTaskRunner::ProcessTask(task.get()); |
| 1551 cache.UnrefImage(draw_image); |
| 1552 } |
| 1553 } |
| 1554 |
| 1395 } // namespace | 1555 } // namespace |
| 1396 } // namespace cc | 1556 } // namespace cc |
| OLD | NEW |