blob: 8703fe23d39ae7a1ef81592af78b38026bb9809c [file] [log] [blame]
robertphillipsdf7bb472016-02-19 08:19:40 -08001 /*
2 * Copyright 2016 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 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "tests/Test.h"
robertphillipsdf7bb472016-02-19 08:19:40 -08009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkBitmap.h"
11#include "include/core/SkColorFilter.h"
12#include "include/core/SkImage.h"
13#include "include/core/SkImageFilter.h"
14#include "include/core/SkMatrix.h"
Michael Ludwig55edb502019-08-05 10:41:10 -040015#include "include/effects/SkImageFilters.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/core/SkImageFilterCache.h"
17#include "src/core/SkSpecialImage.h"
robertphillipsdf7bb472016-02-19 08:19:40 -080018
Michael Ludwigea071232019-08-26 10:52:15 -040019SK_USE_FLUENT_IMAGE_FILTER_TYPES
20
robertphillipsdf7bb472016-02-19 08:19:40 -080021static const int kSmallerSize = 10;
22static const int kPad = 3;
23static const int kFullSize = kSmallerSize + 2 * kPad;
24
25static SkBitmap create_bm() {
Robert Phillips40b05c32019-09-20 12:40:55 -040026 SkImageInfo ii = SkImageInfo::Make(kFullSize, kFullSize, kRGBA_8888_SkColorType,
27 kPremul_SkAlphaType);
28
robertphillipsdf7bb472016-02-19 08:19:40 -080029 SkBitmap bm;
Robert Phillips40b05c32019-09-20 12:40:55 -040030 bm.allocPixels(ii);
robertphillipsdf7bb472016-02-19 08:19:40 -080031 bm.eraseColor(SK_ColorTRANSPARENT);
32 return bm;
33}
34
Ben Wagnerda926db2018-05-03 14:39:57 -040035static sk_sp<SkImageFilter> make_filter() {
Michael Ludwigea071232019-08-26 10:52:15 -040036 sk_sp<SkColorFilter> filter(SkColorFilters::Blend(SK_ColorBLUE, SkBlendMode::kSrcIn));
Michael Ludwig55edb502019-08-05 10:41:10 -040037 return SkImageFilters::ColorFilter(std::move(filter), nullptr, nullptr);
Ben Wagnerda926db2018-05-03 14:39:57 -040038}
39
robertphillipsdf7bb472016-02-19 08:19:40 -080040// Ensure the cache can return a cached image
41static void test_find_existing(skiatest::Reporter* reporter,
robertphillips37bd7c32016-03-17 14:31:39 -070042 const sk_sp<SkSpecialImage>& image,
43 const sk_sp<SkSpecialImage>& subset) {
robertphillipsdf7bb472016-02-19 08:19:40 -080044 static const size_t kCacheSize = 1000000;
Hal Canary342b7ac2016-11-04 11:49:42 -040045 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -080046
47 SkIRect clip = SkIRect::MakeWH(100, 100);
senorblanco900c3672016-04-27 11:31:23 -070048 SkImageFilterCacheKey key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
49 SkImageFilterCacheKey key2(0, SkMatrix::I(), clip, subset->uniqueID(), subset->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -080050
51 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -040052 auto filter = make_filter();
Michael Ludwig05a777d2019-10-02 13:38:29 -040053 cache->set(key1, filter.get(),
54 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
robertphillipsdf7bb472016-02-19 08:19:40 -080055
Michael Ludwigea071232019-08-26 10:52:15 -040056 skif::FilterResult<For::kOutput> foundImage;
57 REPORTER_ASSERT(reporter, cache->get(key1, &foundImage));
Michael Ludwig05a777d2019-10-02 13:38:29 -040058 REPORTER_ASSERT(reporter, offset == SkIPoint(foundImage.layerOrigin()));
robertphillipsdf7bb472016-02-19 08:19:40 -080059
Michael Ludwigea071232019-08-26 10:52:15 -040060 REPORTER_ASSERT(reporter, !cache->get(key2, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -080061}
62
63// If either id is different or the clip or the matrix are different the
64// cached image won't be found. Even if it is caching the same bitmap.
65static void test_dont_find_if_diff_key(skiatest::Reporter* reporter,
robertphillips37bd7c32016-03-17 14:31:39 -070066 const sk_sp<SkSpecialImage>& image,
67 const sk_sp<SkSpecialImage>& subset) {
robertphillipsdf7bb472016-02-19 08:19:40 -080068 static const size_t kCacheSize = 1000000;
Hal Canary342b7ac2016-11-04 11:49:42 -040069 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -080070
71 SkIRect clip1 = SkIRect::MakeWH(100, 100);
72 SkIRect clip2 = SkIRect::MakeWH(200, 200);
senorblanco900c3672016-04-27 11:31:23 -070073 SkImageFilterCacheKey key0(0, SkMatrix::I(), clip1, image->uniqueID(), image->subset());
74 SkImageFilterCacheKey key1(1, SkMatrix::I(), clip1, image->uniqueID(), image->subset());
75 SkImageFilterCacheKey key2(0, SkMatrix::MakeTrans(5, 5), clip1,
robertphillipsdf7bb472016-02-19 08:19:40 -080076 image->uniqueID(), image->subset());
senorblanco900c3672016-04-27 11:31:23 -070077 SkImageFilterCacheKey key3(0, SkMatrix::I(), clip2, image->uniqueID(), image->subset());
78 SkImageFilterCacheKey key4(0, SkMatrix::I(), clip1, subset->uniqueID(), subset->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -080079
80 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -040081 auto filter = make_filter();
Michael Ludwig05a777d2019-10-02 13:38:29 -040082 cache->set(key0, filter.get(),
83 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
robertphillipsdf7bb472016-02-19 08:19:40 -080084
Michael Ludwigea071232019-08-26 10:52:15 -040085 skif::FilterResult<For::kOutput> foundImage;
86 REPORTER_ASSERT(reporter, !cache->get(key1, &foundImage));
87 REPORTER_ASSERT(reporter, !cache->get(key2, &foundImage));
88 REPORTER_ASSERT(reporter, !cache->get(key3, &foundImage));
89 REPORTER_ASSERT(reporter, !cache->get(key4, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -080090}
91
92// Test purging when the max cache size is exceeded
robertphillips37bd7c32016-03-17 14:31:39 -070093static void test_internal_purge(skiatest::Reporter* reporter, const sk_sp<SkSpecialImage>& image) {
robertphillipsdf7bb472016-02-19 08:19:40 -080094 SkASSERT(image->getSize());
mtklein03762fe2016-02-21 13:36:50 -080095 const size_t kCacheSize = image->getSize() + 10;
Hal Canary342b7ac2016-11-04 11:49:42 -040096 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -080097
98 SkIRect clip = SkIRect::MakeWH(100, 100);
senorblanco900c3672016-04-27 11:31:23 -070099 SkImageFilterCacheKey key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
100 SkImageFilterCacheKey key2(1, SkMatrix::I(), clip, image->uniqueID(), image->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -0800101
102 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -0400103 auto filter1 = make_filter();
Michael Ludwig05a777d2019-10-02 13:38:29 -0400104 cache->set(key1, filter1.get(),
105 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
robertphillipsdf7bb472016-02-19 08:19:40 -0800106
Michael Ludwigea071232019-08-26 10:52:15 -0400107 skif::FilterResult<For::kOutput> foundImage;
108 REPORTER_ASSERT(reporter, cache->get(key1, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800109
110 // This should knock the first one out of the cache
Ben Wagnerda926db2018-05-03 14:39:57 -0400111 auto filter2 = make_filter();
Michael Ludwig05a777d2019-10-02 13:38:29 -0400112 cache->set(key2, filter2.get(),
113 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
robertphillipsdf7bb472016-02-19 08:19:40 -0800114
Michael Ludwigea071232019-08-26 10:52:15 -0400115 REPORTER_ASSERT(reporter, cache->get(key2, &foundImage));
116 REPORTER_ASSERT(reporter, !cache->get(key1, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800117}
118
xidachen185a3792017-06-29 11:19:42 -0400119// Exercise the purgeByKey and purge methods
robertphillipsdf7bb472016-02-19 08:19:40 -0800120static void test_explicit_purging(skiatest::Reporter* reporter,
robertphillips37bd7c32016-03-17 14:31:39 -0700121 const sk_sp<SkSpecialImage>& image,
122 const sk_sp<SkSpecialImage>& subset) {
robertphillipsdf7bb472016-02-19 08:19:40 -0800123 static const size_t kCacheSize = 1000000;
Hal Canary342b7ac2016-11-04 11:49:42 -0400124 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -0800125
126 SkIRect clip = SkIRect::MakeWH(100, 100);
senorblanco900c3672016-04-27 11:31:23 -0700127 SkImageFilterCacheKey key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
128 SkImageFilterCacheKey key2(1, SkMatrix::I(), clip, subset->uniqueID(), image->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -0800129
130 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -0400131 auto filter1 = make_filter();
132 auto filter2 = make_filter();
Michael Ludwig05a777d2019-10-02 13:38:29 -0400133 cache->set(key1, filter1.get(),
134 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
135 cache->set(key2, filter2.get(),
136 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
robertphillipsbde57ed2016-04-18 14:49:57 -0700137 SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->count());)
robertphillipsdf7bb472016-02-19 08:19:40 -0800138
Michael Ludwigea071232019-08-26 10:52:15 -0400139 skif::FilterResult<For::kOutput> foundImage;
140 REPORTER_ASSERT(reporter, cache->get(key1, &foundImage));
141 REPORTER_ASSERT(reporter, cache->get(key2, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800142
Ben Wagnerda926db2018-05-03 14:39:57 -0400143 cache->purgeByImageFilter(filter1.get());
robertphillipsbde57ed2016-04-18 14:49:57 -0700144 SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->count());)
robertphillipsdf7bb472016-02-19 08:19:40 -0800145
Michael Ludwigea071232019-08-26 10:52:15 -0400146 REPORTER_ASSERT(reporter, !cache->get(key1, &foundImage));
147 REPORTER_ASSERT(reporter, cache->get(key2, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800148
149 cache->purge();
robertphillipsbde57ed2016-04-18 14:49:57 -0700150 SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->count());)
robertphillipsdf7bb472016-02-19 08:19:40 -0800151
Michael Ludwigea071232019-08-26 10:52:15 -0400152 REPORTER_ASSERT(reporter, !cache->get(key1, &foundImage));
153 REPORTER_ASSERT(reporter, !cache->get(key2, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800154}
155
156DEF_TEST(ImageFilterCache_RasterBacked, reporter) {
157 SkBitmap srcBM = create_bm();
158
159 const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
160
robertphillips3e302272016-04-20 11:48:36 -0700161 sk_sp<SkSpecialImage> fullImg(SkSpecialImage::MakeFromRaster(full, srcBM));
robertphillipsdf7bb472016-02-19 08:19:40 -0800162
163 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
164
robertphillips3e302272016-04-20 11:48:36 -0700165 sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeFromRaster(subset, srcBM));
robertphillipsdf7bb472016-02-19 08:19:40 -0800166
167 test_find_existing(reporter, fullImg, subsetImg);
168 test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
169 test_internal_purge(reporter, fullImg);
170 test_explicit_purging(reporter, fullImg, subsetImg);
171}
172
robertphillipsdf7bb472016-02-19 08:19:40 -0800173
robertphillipscbc5bcc2016-02-19 10:41:12 -0800174// Shared test code for both the raster and gpu-backed image cases
Robert Phillips27467652019-01-10 16:34:22 -0500175static void test_image_backed(skiatest::Reporter* reporter,
176 GrContext* context,
177 const sk_sp<SkImage>& srcImage) {
robertphillipsdf7bb472016-02-19 08:19:40 -0800178 const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
179
Robert Phillips27467652019-01-10 16:34:22 -0500180 sk_sp<SkSpecialImage> fullImg(SkSpecialImage::MakeFromImage(context, full, srcImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800181
182 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
183
Robert Phillips27467652019-01-10 16:34:22 -0500184 sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeFromImage(context, subset, srcImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800185
186 test_find_existing(reporter, fullImg, subsetImg);
187 test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
188 test_internal_purge(reporter, fullImg);
189 test_explicit_purging(reporter, fullImg, subsetImg);
190}
191
robertphillipscbc5bcc2016-02-19 10:41:12 -0800192DEF_TEST(ImageFilterCache_ImageBackedRaster, reporter) {
193 SkBitmap srcBM = create_bm();
194
reed9ce9d672016-03-17 10:51:11 -0700195 sk_sp<SkImage> srcImage(SkImage::MakeFromBitmap(srcBM));
robertphillipscbc5bcc2016-02-19 10:41:12 -0800196
Robert Phillips27467652019-01-10 16:34:22 -0500197 test_image_backed(reporter, nullptr, srcImage);
robertphillipscbc5bcc2016-02-19 10:41:12 -0800198}
199
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500200#include "include/gpu/GrContext.h"
201#include "include/gpu/GrTexture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500202#include "src/gpu/GrContextPriv.h"
203#include "src/gpu/GrProxyProvider.h"
204#include "src/gpu/GrResourceProvider.h"
205#include "src/gpu/GrSurfaceProxyPriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -0400206#include "src/gpu/GrTextureProxy.h"
robertphillipsdf7bb472016-02-19 08:19:40 -0800207
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500208static sk_sp<GrTextureProxy> create_proxy(GrProxyProvider* proxyProvider) {
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500209 SkBitmap srcBM = create_bm();
Brian Osman2700abc2018-09-12 10:19:41 -0400210 sk_sp<SkImage> srcImage(SkImage::MakeFromBitmap(srcBM));
Brian Salomon96b383a2019-08-13 16:55:41 -0400211 return proxyProvider->createTextureProxy(srcImage, 1, SkBudgeted::kYes, SkBackingFit::kExact);
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500212}
213
egdanielab527a52016-06-28 08:07:26 -0700214DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCache_ImageBackedGPU, reporter, ctxInfo) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400215 GrContext* context = ctxInfo.grContext();
216
Robert Phillips9da87e02019-02-04 13:26:26 -0500217 sk_sp<GrTextureProxy> srcProxy(create_proxy(context->priv().proxyProvider()));
Robert Phillipse78b7252017-04-06 07:59:41 -0400218 if (!srcProxy) {
219 return;
220 }
221
Robert Phillips9da87e02019-02-04 13:26:26 -0500222 if (!srcProxy->instantiate(context->priv().resourceProvider())) {
robertphillipscbc5bcc2016-02-19 10:41:12 -0800223 return;
224 }
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400225 GrTexture* tex = srcProxy->peekTexture();
robertphillipscbc5bcc2016-02-19 10:41:12 -0800226
Robert Phillipsb67821d2017-12-13 15:00:45 -0500227 GrBackendTexture backendTex = tex->getBackendTexture();
228
Greg Daniel7ef28f32017-04-20 16:41:55 +0000229 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
Robert Phillipse78b7252017-04-06 07:59:41 -0400230 sk_sp<SkImage> srcImage(SkImage::MakeFromTexture(context,
Greg Daniel7ef28f32017-04-20 16:41:55 +0000231 backendTex,
232 texOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -0500233 kRGBA_8888_SkColorType,
234 kPremul_SkAlphaType, nullptr,
235 nullptr, nullptr));
robertphillipscbc5bcc2016-02-19 10:41:12 -0800236 if (!srcImage) {
237 return;
238 }
239
Robert Phillips3390e152017-01-31 17:53:34 -0500240 GrSurfaceOrigin readBackOrigin;
Robert Phillipsc5509952018-04-04 15:54:55 -0400241 GrBackendTexture readBackBackendTex = srcImage->getBackendTexture(false, &readBackOrigin);
242 if (!GrBackendTexture::TestingOnly_Equals(readBackBackendTex, backendTex)) {
243 ERRORF(reporter, "backend mismatch\n");
Robert Phillips3390e152017-01-31 17:53:34 -0500244 }
Robert Phillipsc5509952018-04-04 15:54:55 -0400245 REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(readBackBackendTex, backendTex));
246
Greg Daniel7ef28f32017-04-20 16:41:55 +0000247 if (readBackOrigin != texOrigin) {
248 ERRORF(reporter, "origin mismatch %d %d\n", readBackOrigin, texOrigin);
Robert Phillips3390e152017-01-31 17:53:34 -0500249 }
Greg Daniel7ef28f32017-04-20 16:41:55 +0000250 REPORTER_ASSERT(reporter, readBackOrigin == texOrigin);
Robert Phillips3390e152017-01-31 17:53:34 -0500251
Robert Phillips27467652019-01-10 16:34:22 -0500252 test_image_backed(reporter, context, srcImage);
robertphillipscbc5bcc2016-02-19 10:41:12 -0800253}
254
bsalomon68d91342016-04-12 09:59:58 -0700255DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCache_GPUBacked, reporter, ctxInfo) {
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500256 GrContext* context = ctxInfo.grContext();
robertphillipscbc5bcc2016-02-19 10:41:12 -0800257
Robert Phillips9da87e02019-02-04 13:26:26 -0500258 sk_sp<GrTextureProxy> srcProxy(create_proxy(context->priv().proxyProvider()));
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500259 if (!srcProxy) {
robertphillipsdf7bb472016-02-19 08:19:40 -0800260 return;
261 }
262
263 const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
264
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500265 sk_sp<SkSpecialImage> fullImg(SkSpecialImage::MakeDeferredFromGpu(
266 context, full,
robertphillips37bd7c32016-03-17 14:31:39 -0700267 kNeedNewImageUniqueID_SpecialImage,
Robert Phillips40b05c32019-09-20 12:40:55 -0400268 srcProxy,
269 GrColorType::kRGBA_8888, nullptr));
robertphillipsdf7bb472016-02-19 08:19:40 -0800270
271 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
272
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500273 sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeDeferredFromGpu(
274 context, subset,
robertphillipsdf7bb472016-02-19 08:19:40 -0800275 kNeedNewImageUniqueID_SpecialImage,
Robert Phillips40b05c32019-09-20 12:40:55 -0400276 srcProxy,
277 GrColorType::kRGBA_8888, nullptr));
robertphillipsdf7bb472016-02-19 08:19:40 -0800278
279 test_find_existing(reporter, fullImg, subsetImg);
280 test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
281 test_internal_purge(reporter, fullImg);
282 test_explicit_purging(reporter, fullImg, subsetImg);
283}