blob: 0e941758eede8bce9de3d51d53376eb9b398c3e7 [file] [log] [blame]
halcanary805ef152014-07-17 06:58:01 -07001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
reed30ad5302014-09-16 10:39:55 -07007
halcanary805ef152014-07-17 06:58:01 -07008#include "Test.h"
reed04617132014-08-21 09:46:49 -07009#include "SkBitmapCache.h"
reed30ad5302014-09-16 10:39:55 -070010#include "SkCanvas.h"
danakj790ffe32014-09-11 10:49:52 -070011#include "SkDiscardableMemoryPool.h"
reed30ad5302014-09-16 10:39:55 -070012#include "SkGraphics.h"
13#include "SkResourceCache.h"
halcanary805ef152014-07-17 06:58:01 -070014
15static const int kCanvasSize = 1;
16static const int kBitmapSize = 16;
17static const int kScale = 8;
18
halcanary1d1795b2014-07-18 09:18:40 -070019static bool is_in_scaled_image_cache(const SkBitmap& orig,
20 SkScalar xScale,
21 SkScalar yScale) {
22 SkBitmap scaled;
humperd73c1692014-08-28 14:27:42 -070023 float roundedImageWidth = SkScalarRoundToScalar(orig.width() * xScale);
24 float roundedImageHeight = SkScalarRoundToScalar(orig.height() * xScale);
25 return SkBitmapCache::Find(orig, roundedImageWidth, roundedImageHeight, &scaled);
halcanary1d1795b2014-07-18 09:18:40 -070026}
27
28// Draw a scaled bitmap, then return true iff it has been cached.
29static bool test_scaled_image_cache_useage() {
halcanary805ef152014-07-17 06:58:01 -070030 SkAutoTUnref<SkCanvas> canvas(
31 SkCanvas::NewRasterN32(kCanvasSize, kCanvasSize));
32 SkBitmap bitmap;
reed84825042014-09-02 12:50:45 -070033 bitmap.allocN32Pixels(kBitmapSize, kBitmapSize);
halcanary0db38cc2014-07-17 10:17:28 -070034 bitmap.eraseColor(0xFFFFFFFF);
halcanary1d1795b2014-07-18 09:18:40 -070035 SkScalar scale = SkIntToScalar(kScale);
36 SkScalar scaledSize = SkIntToScalar(kBitmapSize) * scale;
halcanary805ef152014-07-17 06:58:01 -070037 canvas->clipRect(SkRect::MakeLTRB(0, 0, scaledSize, scaledSize));
38 SkPaint paint;
39 paint.setFilterLevel(SkPaint::kHigh_FilterLevel);
halcanary1d1795b2014-07-18 09:18:40 -070040
halcanary805ef152014-07-17 06:58:01 -070041 canvas->drawBitmapRect(bitmap,
42 SkRect::MakeLTRB(0, 0, scaledSize, scaledSize),
43 &paint);
halcanary1d1795b2014-07-18 09:18:40 -070044
45 return is_in_scaled_image_cache(bitmap, scale, scale);
halcanary805ef152014-07-17 06:58:01 -070046}
47
48// http://crbug.com/389439
reed011f39a2014-08-28 13:35:23 -070049DEF_TEST(ResourceCache_SingleAllocationByteLimit, reporter) {
50 size_t originalByteLimit = SkGraphics::GetResourceCacheTotalByteLimit();
halcanary805ef152014-07-17 06:58:01 -070051 size_t originalAllocationLimit =
reed011f39a2014-08-28 13:35:23 -070052 SkGraphics::GetResourceCacheSingleAllocationByteLimit();
halcanary805ef152014-07-17 06:58:01 -070053
54 size_t size = kBitmapSize * kScale * kBitmapSize * kScale
55 * SkColorTypeBytesPerPixel(kN32_SkColorType);
56
reed011f39a2014-08-28 13:35:23 -070057 SkGraphics::SetResourceCacheTotalByteLimit(0); // clear cache
58 SkGraphics::SetResourceCacheTotalByteLimit(2 * size);
59 SkGraphics::SetResourceCacheSingleAllocationByteLimit(0); // No limit
halcanary805ef152014-07-17 06:58:01 -070060
halcanary1d1795b2014-07-18 09:18:40 -070061 REPORTER_ASSERT(reporter, test_scaled_image_cache_useage());
halcanary805ef152014-07-17 06:58:01 -070062
reed011f39a2014-08-28 13:35:23 -070063 SkGraphics::SetResourceCacheTotalByteLimit(0); // clear cache
64 SkGraphics::SetResourceCacheTotalByteLimit(2 * size);
65 SkGraphics::SetResourceCacheSingleAllocationByteLimit(size * 2); // big enough
halcanary805ef152014-07-17 06:58:01 -070066
halcanary1d1795b2014-07-18 09:18:40 -070067 REPORTER_ASSERT(reporter, test_scaled_image_cache_useage());
halcanary805ef152014-07-17 06:58:01 -070068
reed011f39a2014-08-28 13:35:23 -070069 SkGraphics::SetResourceCacheTotalByteLimit(0); // clear cache
70 SkGraphics::SetResourceCacheTotalByteLimit(2 * size);
71 SkGraphics::SetResourceCacheSingleAllocationByteLimit(size / 2); // too small
halcanary805ef152014-07-17 06:58:01 -070072
halcanary1d1795b2014-07-18 09:18:40 -070073 REPORTER_ASSERT(reporter, !test_scaled_image_cache_useage());
halcanary805ef152014-07-17 06:58:01 -070074
reed011f39a2014-08-28 13:35:23 -070075 SkGraphics::SetResourceCacheSingleAllocationByteLimit(originalAllocationLimit);
76 SkGraphics::SetResourceCacheTotalByteLimit(originalByteLimit);
halcanary805ef152014-07-17 06:58:01 -070077}
piotaixr42b0dfe2014-09-03 11:33:13 -070078
reed30ad5302014-09-16 10:39:55 -070079////////////////////////////////////////////////////////////////////////////////////////
mtklein26abcf12014-09-04 10:50:53 -070080
reed30ad5302014-09-16 10:39:55 -070081static void make_bitmap(SkBitmap* bitmap, const SkImageInfo& info, SkBitmap::Allocator* allocator) {
bsalomon49f085d2014-09-05 13:34:00 -070082 if (allocator) {
reed30ad5302014-09-16 10:39:55 -070083 bitmap->setInfo(info);
84 allocator->allocPixelRef(bitmap, 0);
piotaixr42b0dfe2014-09-03 11:33:13 -070085 } else {
reed30ad5302014-09-16 10:39:55 -070086 bitmap->allocPixels(info);
piotaixr42b0dfe2014-09-03 11:33:13 -070087 }
piotaixr42b0dfe2014-09-03 11:33:13 -070088}
89
90// http://skbug.com/2894
91DEF_TEST(BitmapCache_add_rect, reporter) {
reed30ad5302014-09-16 10:39:55 -070092 SkResourceCache::DiscardableFactory factory = SkResourceCache::GetDiscardableFactory();
93 SkBitmap::Allocator* allocator = SkBitmapCache::GetAllocator();
94
95 SkAutoTDelete<SkResourceCache> cache;
96 if (factory) {
97 cache.reset(SkNEW_ARGS(SkResourceCache, (factory)));
98 } else {
99 const size_t byteLimit = 100 * 1024;
100 cache.reset(SkNEW_ARGS(SkResourceCache, (byteLimit)));
101 }
102 SkBitmap cachedBitmap;
103 make_bitmap(&cachedBitmap, SkImageInfo::MakeN32Premul(5, 5), allocator);
piotaixr42b0dfe2014-09-03 11:33:13 -0700104 cachedBitmap.setImmutable();
105
reed30ad5302014-09-16 10:39:55 -0700106 SkBitmap bm;
107 SkIRect rect = SkIRect::MakeWH(5, 5);
108
piotaixr42b0dfe2014-09-03 11:33:13 -0700109 // Wrong subset size
reed30ad5302014-09-16 10:39:55 -0700110 REPORTER_ASSERT(reporter, !SkBitmapCache::Add(cachedBitmap.getGenerationID(), SkIRect::MakeWH(4, 6), cachedBitmap, cache));
111 REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
piotaixr42b0dfe2014-09-03 11:33:13 -0700112 // Wrong offset value
reed30ad5302014-09-16 10:39:55 -0700113 REPORTER_ASSERT(reporter, !SkBitmapCache::Add(cachedBitmap.getGenerationID(), SkIRect::MakeXYWH(-1, 0, 5, 5), cachedBitmap, cache));
114 REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
piotaixr42b0dfe2014-09-03 11:33:13 -0700115
116 // Should not be in the cache
reed30ad5302014-09-16 10:39:55 -0700117 REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
piotaixr42b0dfe2014-09-03 11:33:13 -0700118
reed30ad5302014-09-16 10:39:55 -0700119 REPORTER_ASSERT(reporter, SkBitmapCache::Add(cachedBitmap.getGenerationID(), rect, cachedBitmap, cache));
piotaixr42b0dfe2014-09-03 11:33:13 -0700120 // Should be in the cache, we just added it
reed30ad5302014-09-16 10:39:55 -0700121 REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
piotaixr42b0dfe2014-09-03 11:33:13 -0700122}
danakj790ffe32014-09-11 10:49:52 -0700123
reed9d93c2e2014-10-08 05:17:12 -0700124#include "SkMipMap.h"
125
126enum LockedState {
127 kNotLocked,
128 kLocked,
129};
130
131enum CachedState {
132 kNotInCache,
133 kInCache,
134};
135
136static void check_data(skiatest::Reporter* reporter, const SkCachedData* data,
137 int refcnt, CachedState cacheState, LockedState lockedState) {
138 REPORTER_ASSERT(reporter, data->testing_only_getRefCnt() == refcnt);
139 REPORTER_ASSERT(reporter, data->testing_only_isInCache() == (kInCache == cacheState));
140 bool isLocked = (data->data() != NULL);
141 REPORTER_ASSERT(reporter, isLocked == (lockedState == kLocked));
142}
143
144static void test_mipmapcache(skiatest::Reporter* reporter, SkResourceCache* cache) {
145 cache->purgeAll();
146
147 SkBitmap src;
148 src.allocN32Pixels(5, 5);
149 src.setImmutable();
150
151 const SkMipMap* mipmap = SkMipMapCache::FindAndRef(src, cache);
152 REPORTER_ASSERT(reporter, NULL == mipmap);
153
154 mipmap = SkMipMapCache::AddAndRef(src, cache);
155 REPORTER_ASSERT(reporter, mipmap);
156 check_data(reporter, mipmap, 2, kInCache, kLocked);
157
158 mipmap->unref();
159 // tricky, since technically after this I'm no longer an owner, but since the cache is
160 // local, I know it won't get purged behind my back
161 check_data(reporter, mipmap, 1, kInCache, kNotLocked);
162
163 // find us again
164 mipmap = SkMipMapCache::FindAndRef(src, cache);
165 check_data(reporter, mipmap, 2, kInCache, kLocked);
166
167 cache->purgeAll();
168 check_data(reporter, mipmap, 1, kNotInCache, kLocked);
169
170 mipmap->unref();
171}
172
danakj790ffe32014-09-11 10:49:52 -0700173DEF_TEST(BitmapCache_discarded_bitmap, reporter) {
reed30ad5302014-09-16 10:39:55 -0700174 SkResourceCache::DiscardableFactory factory = SkResourceCache::GetDiscardableFactory();
175 SkBitmap::Allocator* allocator = SkBitmapCache::GetAllocator();
176
177 SkAutoTDelete<SkResourceCache> cache;
178 if (factory) {
179 cache.reset(SkNEW_ARGS(SkResourceCache, (factory)));
180 } else {
181 const size_t byteLimit = 100 * 1024;
182 cache.reset(SkNEW_ARGS(SkResourceCache, (byteLimit)));
183 }
184 SkBitmap cachedBitmap;
185 make_bitmap(&cachedBitmap, SkImageInfo::MakeN32Premul(5, 5), allocator);
danakj790ffe32014-09-11 10:49:52 -0700186 cachedBitmap.setImmutable();
187 cachedBitmap.unlockPixels();
188
reed30ad5302014-09-16 10:39:55 -0700189 SkBitmap bm;
190 SkIRect rect = SkIRect::MakeWH(5, 5);
191
danakj790ffe32014-09-11 10:49:52 -0700192 // Add a bitmap to the cache.
reed30ad5302014-09-16 10:39:55 -0700193 REPORTER_ASSERT(reporter, SkBitmapCache::Add(cachedBitmap.getGenerationID(), rect, cachedBitmap, cache));
194 REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
danakj790ffe32014-09-11 10:49:52 -0700195
196 // Finding more than once works fine.
reed30ad5302014-09-16 10:39:55 -0700197 REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
danakj790ffe32014-09-11 10:49:52 -0700198 bm.unlockPixels();
199
200 // Drop the pixels in the bitmap.
reed30ad5302014-09-16 10:39:55 -0700201 if (factory) {
202 REPORTER_ASSERT(reporter, SkGetGlobalDiscardableMemoryPool()->getRAMUsed() > 0);
203 SkGetGlobalDiscardableMemoryPool()->dumpPool();
204 REPORTER_ASSERT(reporter, SkGetGlobalDiscardableMemoryPool()->getRAMUsed() == 0);
danakj790ffe32014-09-11 10:49:52 -0700205
reed30ad5302014-09-16 10:39:55 -0700206 // The bitmap is not in the cache since it has been dropped.
207 REPORTER_ASSERT(reporter, !SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
208 }
danakj790ffe32014-09-11 10:49:52 -0700209
reed30ad5302014-09-16 10:39:55 -0700210 make_bitmap(&cachedBitmap, SkImageInfo::MakeN32Premul(5, 5), allocator);
danakj790ffe32014-09-11 10:49:52 -0700211 cachedBitmap.setImmutable();
212 cachedBitmap.unlockPixels();
213
214 // We can add the bitmap back to the cache and find it again.
reed30ad5302014-09-16 10:39:55 -0700215 REPORTER_ASSERT(reporter, SkBitmapCache::Add(cachedBitmap.getGenerationID(), rect, cachedBitmap, cache));
216 REPORTER_ASSERT(reporter, SkBitmapCache::Find(cachedBitmap.getGenerationID(), rect, &bm, cache));
reed9d93c2e2014-10-08 05:17:12 -0700217
218 test_mipmapcache(reporter, cache);
danakj790ffe32014-09-11 10:49:52 -0700219}