blob: 16cd6ae9ef062398171594dd32099302e8ceef8f [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 Ludwigea071232019-08-26 10:52:15 -040053 cache->set(key1, filter.get(), skif::FilterResult<For::kOutput>(image, offset));
robertphillipsdf7bb472016-02-19 08:19:40 -080054
Michael Ludwigea071232019-08-26 10:52:15 -040055 skif::FilterResult<For::kOutput> foundImage;
56 REPORTER_ASSERT(reporter, cache->get(key1, &foundImage));
57 REPORTER_ASSERT(reporter, offset == foundImage.origin());
robertphillipsdf7bb472016-02-19 08:19:40 -080058
Michael Ludwigea071232019-08-26 10:52:15 -040059 REPORTER_ASSERT(reporter, !cache->get(key2, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -080060}
61
62// If either id is different or the clip or the matrix are different the
63// cached image won't be found. Even if it is caching the same bitmap.
64static void test_dont_find_if_diff_key(skiatest::Reporter* reporter,
robertphillips37bd7c32016-03-17 14:31:39 -070065 const sk_sp<SkSpecialImage>& image,
66 const sk_sp<SkSpecialImage>& subset) {
robertphillipsdf7bb472016-02-19 08:19:40 -080067 static const size_t kCacheSize = 1000000;
Hal Canary342b7ac2016-11-04 11:49:42 -040068 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -080069
70 SkIRect clip1 = SkIRect::MakeWH(100, 100);
71 SkIRect clip2 = SkIRect::MakeWH(200, 200);
senorblanco900c3672016-04-27 11:31:23 -070072 SkImageFilterCacheKey key0(0, SkMatrix::I(), clip1, image->uniqueID(), image->subset());
73 SkImageFilterCacheKey key1(1, SkMatrix::I(), clip1, image->uniqueID(), image->subset());
74 SkImageFilterCacheKey key2(0, SkMatrix::MakeTrans(5, 5), clip1,
robertphillipsdf7bb472016-02-19 08:19:40 -080075 image->uniqueID(), image->subset());
senorblanco900c3672016-04-27 11:31:23 -070076 SkImageFilterCacheKey key3(0, SkMatrix::I(), clip2, image->uniqueID(), image->subset());
77 SkImageFilterCacheKey key4(0, SkMatrix::I(), clip1, subset->uniqueID(), subset->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -080078
79 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -040080 auto filter = make_filter();
Michael Ludwigea071232019-08-26 10:52:15 -040081 cache->set(key0, filter.get(), skif::FilterResult<For::kOutput>(image, offset));
robertphillipsdf7bb472016-02-19 08:19:40 -080082
Michael Ludwigea071232019-08-26 10:52:15 -040083 skif::FilterResult<For::kOutput> foundImage;
84 REPORTER_ASSERT(reporter, !cache->get(key1, &foundImage));
85 REPORTER_ASSERT(reporter, !cache->get(key2, &foundImage));
86 REPORTER_ASSERT(reporter, !cache->get(key3, &foundImage));
87 REPORTER_ASSERT(reporter, !cache->get(key4, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -080088}
89
90// Test purging when the max cache size is exceeded
robertphillips37bd7c32016-03-17 14:31:39 -070091static void test_internal_purge(skiatest::Reporter* reporter, const sk_sp<SkSpecialImage>& image) {
robertphillipsdf7bb472016-02-19 08:19:40 -080092 SkASSERT(image->getSize());
mtklein03762fe2016-02-21 13:36:50 -080093 const size_t kCacheSize = image->getSize() + 10;
Hal Canary342b7ac2016-11-04 11:49:42 -040094 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -080095
96 SkIRect clip = SkIRect::MakeWH(100, 100);
senorblanco900c3672016-04-27 11:31:23 -070097 SkImageFilterCacheKey key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
98 SkImageFilterCacheKey key2(1, SkMatrix::I(), clip, image->uniqueID(), image->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -080099
100 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -0400101 auto filter1 = make_filter();
Michael Ludwigea071232019-08-26 10:52:15 -0400102 cache->set(key1, filter1.get(), skif::FilterResult<For::kOutput>(image, offset));
robertphillipsdf7bb472016-02-19 08:19:40 -0800103
Michael Ludwigea071232019-08-26 10:52:15 -0400104 skif::FilterResult<For::kOutput> foundImage;
105 REPORTER_ASSERT(reporter, cache->get(key1, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800106
107 // This should knock the first one out of the cache
Ben Wagnerda926db2018-05-03 14:39:57 -0400108 auto filter2 = make_filter();
Michael Ludwigea071232019-08-26 10:52:15 -0400109 cache->set(key2, filter2.get(), skif::FilterResult<For::kOutput>(image, offset));
robertphillipsdf7bb472016-02-19 08:19:40 -0800110
Michael Ludwigea071232019-08-26 10:52:15 -0400111 REPORTER_ASSERT(reporter, cache->get(key2, &foundImage));
112 REPORTER_ASSERT(reporter, !cache->get(key1, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800113}
114
xidachen185a3792017-06-29 11:19:42 -0400115// Exercise the purgeByKey and purge methods
robertphillipsdf7bb472016-02-19 08:19:40 -0800116static void test_explicit_purging(skiatest::Reporter* reporter,
robertphillips37bd7c32016-03-17 14:31:39 -0700117 const sk_sp<SkSpecialImage>& image,
118 const sk_sp<SkSpecialImage>& subset) {
robertphillipsdf7bb472016-02-19 08:19:40 -0800119 static const size_t kCacheSize = 1000000;
Hal Canary342b7ac2016-11-04 11:49:42 -0400120 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -0800121
122 SkIRect clip = SkIRect::MakeWH(100, 100);
senorblanco900c3672016-04-27 11:31:23 -0700123 SkImageFilterCacheKey key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
124 SkImageFilterCacheKey key2(1, SkMatrix::I(), clip, subset->uniqueID(), image->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -0800125
126 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -0400127 auto filter1 = make_filter();
128 auto filter2 = make_filter();
Michael Ludwigea071232019-08-26 10:52:15 -0400129 cache->set(key1, filter1.get(), skif::FilterResult<For::kOutput>(image, offset));
130 cache->set(key2, filter2.get(), skif::FilterResult<For::kOutput>(image, offset));
robertphillipsbde57ed2016-04-18 14:49:57 -0700131 SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->count());)
robertphillipsdf7bb472016-02-19 08:19:40 -0800132
Michael Ludwigea071232019-08-26 10:52:15 -0400133 skif::FilterResult<For::kOutput> foundImage;
134 REPORTER_ASSERT(reporter, cache->get(key1, &foundImage));
135 REPORTER_ASSERT(reporter, cache->get(key2, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800136
Ben Wagnerda926db2018-05-03 14:39:57 -0400137 cache->purgeByImageFilter(filter1.get());
robertphillipsbde57ed2016-04-18 14:49:57 -0700138 SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->count());)
robertphillipsdf7bb472016-02-19 08:19:40 -0800139
Michael Ludwigea071232019-08-26 10:52:15 -0400140 REPORTER_ASSERT(reporter, !cache->get(key1, &foundImage));
141 REPORTER_ASSERT(reporter, cache->get(key2, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800142
143 cache->purge();
robertphillipsbde57ed2016-04-18 14:49:57 -0700144 SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == 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
150DEF_TEST(ImageFilterCache_RasterBacked, reporter) {
151 SkBitmap srcBM = create_bm();
152
153 const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
154
robertphillips3e302272016-04-20 11:48:36 -0700155 sk_sp<SkSpecialImage> fullImg(SkSpecialImage::MakeFromRaster(full, srcBM));
robertphillipsdf7bb472016-02-19 08:19:40 -0800156
157 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
158
robertphillips3e302272016-04-20 11:48:36 -0700159 sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeFromRaster(subset, srcBM));
robertphillipsdf7bb472016-02-19 08:19:40 -0800160
161 test_find_existing(reporter, fullImg, subsetImg);
162 test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
163 test_internal_purge(reporter, fullImg);
164 test_explicit_purging(reporter, fullImg, subsetImg);
165}
166
robertphillipsdf7bb472016-02-19 08:19:40 -0800167
robertphillipscbc5bcc2016-02-19 10:41:12 -0800168// Shared test code for both the raster and gpu-backed image cases
Robert Phillips27467652019-01-10 16:34:22 -0500169static void test_image_backed(skiatest::Reporter* reporter,
170 GrContext* context,
171 const sk_sp<SkImage>& srcImage) {
robertphillipsdf7bb472016-02-19 08:19:40 -0800172 const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
173
Robert Phillips27467652019-01-10 16:34:22 -0500174 sk_sp<SkSpecialImage> fullImg(SkSpecialImage::MakeFromImage(context, full, srcImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800175
176 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
177
Robert Phillips27467652019-01-10 16:34:22 -0500178 sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeFromImage(context, subset, srcImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800179
180 test_find_existing(reporter, fullImg, subsetImg);
181 test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
182 test_internal_purge(reporter, fullImg);
183 test_explicit_purging(reporter, fullImg, subsetImg);
184}
185
robertphillipscbc5bcc2016-02-19 10:41:12 -0800186DEF_TEST(ImageFilterCache_ImageBackedRaster, reporter) {
187 SkBitmap srcBM = create_bm();
188
reed9ce9d672016-03-17 10:51:11 -0700189 sk_sp<SkImage> srcImage(SkImage::MakeFromBitmap(srcBM));
robertphillipscbc5bcc2016-02-19 10:41:12 -0800190
Robert Phillips27467652019-01-10 16:34:22 -0500191 test_image_backed(reporter, nullptr, srcImage);
robertphillipscbc5bcc2016-02-19 10:41:12 -0800192}
193
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500194#include "include/gpu/GrContext.h"
195#include "include/gpu/GrTexture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500196#include "src/gpu/GrContextPriv.h"
197#include "src/gpu/GrProxyProvider.h"
198#include "src/gpu/GrResourceProvider.h"
199#include "src/gpu/GrSurfaceProxyPriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -0400200#include "src/gpu/GrTextureProxy.h"
robertphillipsdf7bb472016-02-19 08:19:40 -0800201
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500202static sk_sp<GrTextureProxy> create_proxy(GrProxyProvider* proxyProvider) {
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500203 SkBitmap srcBM = create_bm();
Brian Osman2700abc2018-09-12 10:19:41 -0400204 sk_sp<SkImage> srcImage(SkImage::MakeFromBitmap(srcBM));
Brian Salomon96b383a2019-08-13 16:55:41 -0400205 return proxyProvider->createTextureProxy(srcImage, 1, SkBudgeted::kYes, SkBackingFit::kExact);
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500206}
207
egdanielab527a52016-06-28 08:07:26 -0700208DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCache_ImageBackedGPU, reporter, ctxInfo) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400209 GrContext* context = ctxInfo.grContext();
210
Robert Phillips9da87e02019-02-04 13:26:26 -0500211 sk_sp<GrTextureProxy> srcProxy(create_proxy(context->priv().proxyProvider()));
Robert Phillipse78b7252017-04-06 07:59:41 -0400212 if (!srcProxy) {
213 return;
214 }
215
Robert Phillips9da87e02019-02-04 13:26:26 -0500216 if (!srcProxy->instantiate(context->priv().resourceProvider())) {
robertphillipscbc5bcc2016-02-19 10:41:12 -0800217 return;
218 }
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400219 GrTexture* tex = srcProxy->peekTexture();
robertphillipscbc5bcc2016-02-19 10:41:12 -0800220
Robert Phillipsb67821d2017-12-13 15:00:45 -0500221 GrBackendTexture backendTex = tex->getBackendTexture();
222
Greg Daniel7ef28f32017-04-20 16:41:55 +0000223 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
Robert Phillipse78b7252017-04-06 07:59:41 -0400224 sk_sp<SkImage> srcImage(SkImage::MakeFromTexture(context,
Greg Daniel7ef28f32017-04-20 16:41:55 +0000225 backendTex,
226 texOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -0500227 kRGBA_8888_SkColorType,
228 kPremul_SkAlphaType, nullptr,
229 nullptr, nullptr));
robertphillipscbc5bcc2016-02-19 10:41:12 -0800230 if (!srcImage) {
231 return;
232 }
233
Robert Phillips3390e152017-01-31 17:53:34 -0500234 GrSurfaceOrigin readBackOrigin;
Robert Phillipsc5509952018-04-04 15:54:55 -0400235 GrBackendTexture readBackBackendTex = srcImage->getBackendTexture(false, &readBackOrigin);
236 if (!GrBackendTexture::TestingOnly_Equals(readBackBackendTex, backendTex)) {
237 ERRORF(reporter, "backend mismatch\n");
Robert Phillips3390e152017-01-31 17:53:34 -0500238 }
Robert Phillipsc5509952018-04-04 15:54:55 -0400239 REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(readBackBackendTex, backendTex));
240
Greg Daniel7ef28f32017-04-20 16:41:55 +0000241 if (readBackOrigin != texOrigin) {
242 ERRORF(reporter, "origin mismatch %d %d\n", readBackOrigin, texOrigin);
Robert Phillips3390e152017-01-31 17:53:34 -0500243 }
Greg Daniel7ef28f32017-04-20 16:41:55 +0000244 REPORTER_ASSERT(reporter, readBackOrigin == texOrigin);
Robert Phillips3390e152017-01-31 17:53:34 -0500245
Robert Phillips27467652019-01-10 16:34:22 -0500246 test_image_backed(reporter, context, srcImage);
robertphillipscbc5bcc2016-02-19 10:41:12 -0800247}
248
bsalomon68d91342016-04-12 09:59:58 -0700249DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCache_GPUBacked, reporter, ctxInfo) {
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500250 GrContext* context = ctxInfo.grContext();
robertphillipscbc5bcc2016-02-19 10:41:12 -0800251
Robert Phillips9da87e02019-02-04 13:26:26 -0500252 sk_sp<GrTextureProxy> srcProxy(create_proxy(context->priv().proxyProvider()));
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500253 if (!srcProxy) {
robertphillipsdf7bb472016-02-19 08:19:40 -0800254 return;
255 }
256
257 const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
258
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500259 sk_sp<SkSpecialImage> fullImg(SkSpecialImage::MakeDeferredFromGpu(
260 context, full,
robertphillips37bd7c32016-03-17 14:31:39 -0700261 kNeedNewImageUniqueID_SpecialImage,
Robert Phillips40b05c32019-09-20 12:40:55 -0400262 srcProxy,
263 GrColorType::kRGBA_8888, nullptr));
robertphillipsdf7bb472016-02-19 08:19:40 -0800264
265 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
266
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500267 sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeDeferredFromGpu(
268 context, subset,
robertphillipsdf7bb472016-02-19 08:19:40 -0800269 kNeedNewImageUniqueID_SpecialImage,
Robert Phillips40b05c32019-09-20 12:40:55 -0400270 srcProxy,
271 GrColorType::kRGBA_8888, nullptr));
robertphillipsdf7bb472016-02-19 08:19:40 -0800272
273 test_find_existing(reporter, fullImg, subsetImg);
274 test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
275 test_internal_purge(reporter, fullImg);
276 test_explicit_purging(reporter, fullImg, subsetImg);
277}