blob: 46aa8c3dadcf62b96ed2cb9e313076610d8369ea [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);
Greg Daniel6f5441a2020-01-28 17:02:49 -050032 bm.setImmutable();
robertphillipsdf7bb472016-02-19 08:19:40 -080033 return bm;
34}
35
Ben Wagnerda926db2018-05-03 14:39:57 -040036static sk_sp<SkImageFilter> make_filter() {
Michael Ludwigea071232019-08-26 10:52:15 -040037 sk_sp<SkColorFilter> filter(SkColorFilters::Blend(SK_ColorBLUE, SkBlendMode::kSrcIn));
Michael Ludwig55edb502019-08-05 10:41:10 -040038 return SkImageFilters::ColorFilter(std::move(filter), nullptr, nullptr);
Ben Wagnerda926db2018-05-03 14:39:57 -040039}
40
robertphillipsdf7bb472016-02-19 08:19:40 -080041// Ensure the cache can return a cached image
42static void test_find_existing(skiatest::Reporter* reporter,
robertphillips37bd7c32016-03-17 14:31:39 -070043 const sk_sp<SkSpecialImage>& image,
44 const sk_sp<SkSpecialImage>& subset) {
robertphillipsdf7bb472016-02-19 08:19:40 -080045 static const size_t kCacheSize = 1000000;
Hal Canary342b7ac2016-11-04 11:49:42 -040046 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -080047
48 SkIRect clip = SkIRect::MakeWH(100, 100);
senorblanco900c3672016-04-27 11:31:23 -070049 SkImageFilterCacheKey key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
50 SkImageFilterCacheKey key2(0, SkMatrix::I(), clip, subset->uniqueID(), subset->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -080051
52 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -040053 auto filter = make_filter();
Michael Ludwig05a777d2019-10-02 13:38:29 -040054 cache->set(key1, filter.get(),
55 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
robertphillipsdf7bb472016-02-19 08:19:40 -080056
Michael Ludwigea071232019-08-26 10:52:15 -040057 skif::FilterResult<For::kOutput> foundImage;
58 REPORTER_ASSERT(reporter, cache->get(key1, &foundImage));
Michael Ludwig05a777d2019-10-02 13:38:29 -040059 REPORTER_ASSERT(reporter, offset == SkIPoint(foundImage.layerOrigin()));
robertphillipsdf7bb472016-02-19 08:19:40 -080060
Michael Ludwigea071232019-08-26 10:52:15 -040061 REPORTER_ASSERT(reporter, !cache->get(key2, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -080062}
63
64// If either id is different or the clip or the matrix are different the
65// cached image won't be found. Even if it is caching the same bitmap.
66static void test_dont_find_if_diff_key(skiatest::Reporter* reporter,
robertphillips37bd7c32016-03-17 14:31:39 -070067 const sk_sp<SkSpecialImage>& image,
68 const sk_sp<SkSpecialImage>& subset) {
robertphillipsdf7bb472016-02-19 08:19:40 -080069 static const size_t kCacheSize = 1000000;
Hal Canary342b7ac2016-11-04 11:49:42 -040070 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -080071
72 SkIRect clip1 = SkIRect::MakeWH(100, 100);
73 SkIRect clip2 = SkIRect::MakeWH(200, 200);
senorblanco900c3672016-04-27 11:31:23 -070074 SkImageFilterCacheKey key0(0, SkMatrix::I(), clip1, image->uniqueID(), image->subset());
75 SkImageFilterCacheKey key1(1, SkMatrix::I(), clip1, image->uniqueID(), image->subset());
Mike Reed1f607332020-05-21 12:11:27 -040076 SkImageFilterCacheKey key2(0, SkMatrix::Translate(5, 5), clip1,
robertphillipsdf7bb472016-02-19 08:19:40 -080077 image->uniqueID(), image->subset());
senorblanco900c3672016-04-27 11:31:23 -070078 SkImageFilterCacheKey key3(0, SkMatrix::I(), clip2, image->uniqueID(), image->subset());
79 SkImageFilterCacheKey key4(0, SkMatrix::I(), clip1, subset->uniqueID(), subset->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -080080
81 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -040082 auto filter = make_filter();
Michael Ludwig05a777d2019-10-02 13:38:29 -040083 cache->set(key0, filter.get(),
84 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
robertphillipsdf7bb472016-02-19 08:19:40 -080085
Michael Ludwigea071232019-08-26 10:52:15 -040086 skif::FilterResult<For::kOutput> foundImage;
87 REPORTER_ASSERT(reporter, !cache->get(key1, &foundImage));
88 REPORTER_ASSERT(reporter, !cache->get(key2, &foundImage));
89 REPORTER_ASSERT(reporter, !cache->get(key3, &foundImage));
90 REPORTER_ASSERT(reporter, !cache->get(key4, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -080091}
92
93// Test purging when the max cache size is exceeded
robertphillips37bd7c32016-03-17 14:31:39 -070094static void test_internal_purge(skiatest::Reporter* reporter, const sk_sp<SkSpecialImage>& image) {
robertphillipsdf7bb472016-02-19 08:19:40 -080095 SkASSERT(image->getSize());
mtklein03762fe2016-02-21 13:36:50 -080096 const size_t kCacheSize = image->getSize() + 10;
Hal Canary342b7ac2016-11-04 11:49:42 -040097 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -080098
99 SkIRect clip = SkIRect::MakeWH(100, 100);
senorblanco900c3672016-04-27 11:31:23 -0700100 SkImageFilterCacheKey key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
101 SkImageFilterCacheKey key2(1, SkMatrix::I(), clip, image->uniqueID(), image->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -0800102
103 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -0400104 auto filter1 = make_filter();
Michael Ludwig05a777d2019-10-02 13:38:29 -0400105 cache->set(key1, filter1.get(),
106 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
robertphillipsdf7bb472016-02-19 08:19:40 -0800107
Michael Ludwigea071232019-08-26 10:52:15 -0400108 skif::FilterResult<For::kOutput> foundImage;
109 REPORTER_ASSERT(reporter, cache->get(key1, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800110
111 // This should knock the first one out of the cache
Ben Wagnerda926db2018-05-03 14:39:57 -0400112 auto filter2 = make_filter();
Michael Ludwig05a777d2019-10-02 13:38:29 -0400113 cache->set(key2, filter2.get(),
114 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
robertphillipsdf7bb472016-02-19 08:19:40 -0800115
Michael Ludwigea071232019-08-26 10:52:15 -0400116 REPORTER_ASSERT(reporter, cache->get(key2, &foundImage));
117 REPORTER_ASSERT(reporter, !cache->get(key1, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800118}
119
xidachen185a3792017-06-29 11:19:42 -0400120// Exercise the purgeByKey and purge methods
robertphillipsdf7bb472016-02-19 08:19:40 -0800121static void test_explicit_purging(skiatest::Reporter* reporter,
robertphillips37bd7c32016-03-17 14:31:39 -0700122 const sk_sp<SkSpecialImage>& image,
123 const sk_sp<SkSpecialImage>& subset) {
robertphillipsdf7bb472016-02-19 08:19:40 -0800124 static const size_t kCacheSize = 1000000;
Hal Canary342b7ac2016-11-04 11:49:42 -0400125 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -0800126
127 SkIRect clip = SkIRect::MakeWH(100, 100);
senorblanco900c3672016-04-27 11:31:23 -0700128 SkImageFilterCacheKey key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
129 SkImageFilterCacheKey key2(1, SkMatrix::I(), clip, subset->uniqueID(), image->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -0800130
131 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -0400132 auto filter1 = make_filter();
133 auto filter2 = make_filter();
Michael Ludwig05a777d2019-10-02 13:38:29 -0400134 cache->set(key1, filter1.get(),
135 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
136 cache->set(key2, filter2.get(),
137 skif::FilterResult<For::kOutput>(image, skif::LayerSpace<SkIPoint>(offset)));
robertphillipsbde57ed2016-04-18 14:49:57 -0700138 SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->count());)
robertphillipsdf7bb472016-02-19 08:19:40 -0800139
Michael Ludwigea071232019-08-26 10:52:15 -0400140 skif::FilterResult<For::kOutput> foundImage;
141 REPORTER_ASSERT(reporter, cache->get(key1, &foundImage));
142 REPORTER_ASSERT(reporter, cache->get(key2, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800143
Ben Wagnerda926db2018-05-03 14:39:57 -0400144 cache->purgeByImageFilter(filter1.get());
robertphillipsbde57ed2016-04-18 14:49:57 -0700145 SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->count());)
robertphillipsdf7bb472016-02-19 08:19:40 -0800146
Michael Ludwigea071232019-08-26 10:52:15 -0400147 REPORTER_ASSERT(reporter, !cache->get(key1, &foundImage));
148 REPORTER_ASSERT(reporter, cache->get(key2, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800149
150 cache->purge();
robertphillipsbde57ed2016-04-18 14:49:57 -0700151 SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->count());)
robertphillipsdf7bb472016-02-19 08:19:40 -0800152
Michael Ludwigea071232019-08-26 10:52:15 -0400153 REPORTER_ASSERT(reporter, !cache->get(key1, &foundImage));
154 REPORTER_ASSERT(reporter, !cache->get(key2, &foundImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800155}
156
157DEF_TEST(ImageFilterCache_RasterBacked, reporter) {
158 SkBitmap srcBM = create_bm();
159
160 const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
161
robertphillips3e302272016-04-20 11:48:36 -0700162 sk_sp<SkSpecialImage> fullImg(SkSpecialImage::MakeFromRaster(full, srcBM));
robertphillipsdf7bb472016-02-19 08:19:40 -0800163
164 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
165
robertphillips3e302272016-04-20 11:48:36 -0700166 sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeFromRaster(subset, srcBM));
robertphillipsdf7bb472016-02-19 08:19:40 -0800167
168 test_find_existing(reporter, fullImg, subsetImg);
169 test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
170 test_internal_purge(reporter, fullImg);
171 test_explicit_purging(reporter, fullImg, subsetImg);
172}
173
robertphillipsdf7bb472016-02-19 08:19:40 -0800174
robertphillipscbc5bcc2016-02-19 10:41:12 -0800175// Shared test code for both the raster and gpu-backed image cases
Robert Phillips27467652019-01-10 16:34:22 -0500176static void test_image_backed(skiatest::Reporter* reporter,
177 GrContext* context,
178 const sk_sp<SkImage>& srcImage) {
robertphillipsdf7bb472016-02-19 08:19:40 -0800179 const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
180
Robert Phillips27467652019-01-10 16:34:22 -0500181 sk_sp<SkSpecialImage> fullImg(SkSpecialImage::MakeFromImage(context, full, srcImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800182
183 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
184
Robert Phillips27467652019-01-10 16:34:22 -0500185 sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeFromImage(context, subset, srcImage));
robertphillipsdf7bb472016-02-19 08:19:40 -0800186
187 test_find_existing(reporter, fullImg, subsetImg);
188 test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
189 test_internal_purge(reporter, fullImg);
190 test_explicit_purging(reporter, fullImg, subsetImg);
191}
192
robertphillipscbc5bcc2016-02-19 10:41:12 -0800193DEF_TEST(ImageFilterCache_ImageBackedRaster, reporter) {
194 SkBitmap srcBM = create_bm();
195
reed9ce9d672016-03-17 10:51:11 -0700196 sk_sp<SkImage> srcImage(SkImage::MakeFromBitmap(srcBM));
robertphillipscbc5bcc2016-02-19 10:41:12 -0800197
Robert Phillips27467652019-01-10 16:34:22 -0500198 test_image_backed(reporter, nullptr, srcImage);
robertphillipscbc5bcc2016-02-19 10:41:12 -0800199}
200
Robert Phillips6d344c32020-07-06 10:56:46 -0400201#include "include/gpu/GrDirectContext.h"
Greg Daniel6f5441a2020-01-28 17:02:49 -0500202#include "src/gpu/GrBitmapTextureMaker.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500203#include "src/gpu/GrContextPriv.h"
204#include "src/gpu/GrProxyProvider.h"
205#include "src/gpu/GrResourceProvider.h"
206#include "src/gpu/GrSurfaceProxyPriv.h"
Greg Daniel456f9b52020-03-05 19:14:18 +0000207#include "src/gpu/GrTexture.h"
Greg Danielf91aeb22019-06-18 09:58:02 -0400208#include "src/gpu/GrTextureProxy.h"
robertphillipsdf7bb472016-02-19 08:19:40 -0800209
Greg Danielc52db712020-01-28 17:03:46 -0500210static GrSurfaceProxyView create_proxy_view(GrRecordingContext* context) {
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500211 SkBitmap srcBM = create_bm();
Brian Salomonbc074a62020-03-18 10:06:13 -0400212 GrBitmapTextureMaker maker(context, srcBM, GrImageTexGenPolicy::kNew_Uncached_Budgeted);
Brian Salomonecbb0fb2020-02-28 18:07:32 -0500213 return maker.view(GrMipMapped::kNo);
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500214}
215
egdanielab527a52016-06-28 08:07:26 -0700216DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCache_ImageBackedGPU, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400217 auto context = ctxInfo.directContext();
Robert Phillipse78b7252017-04-06 07:59:41 -0400218
Greg Danielc52db712020-01-28 17:03:46 -0500219 GrSurfaceProxyView srcView = create_proxy_view(context);
220 if (!srcView.proxy()) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400221 return;
222 }
223
Greg Danielc52db712020-01-28 17:03:46 -0500224 if (!srcView.proxy()->instantiate(context->priv().resourceProvider())) {
robertphillipscbc5bcc2016-02-19 10:41:12 -0800225 return;
226 }
Greg Danielc52db712020-01-28 17:03:46 -0500227 GrTexture* tex = srcView.proxy()->peekTexture();
robertphillipscbc5bcc2016-02-19 10:41:12 -0800228
Robert Phillipsb67821d2017-12-13 15:00:45 -0500229 GrBackendTexture backendTex = tex->getBackendTexture();
230
Greg Daniel7ef28f32017-04-20 16:41:55 +0000231 GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
Robert Phillipse78b7252017-04-06 07:59:41 -0400232 sk_sp<SkImage> srcImage(SkImage::MakeFromTexture(context,
Greg Daniel7ef28f32017-04-20 16:41:55 +0000233 backendTex,
234 texOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -0500235 kRGBA_8888_SkColorType,
236 kPremul_SkAlphaType, nullptr,
237 nullptr, nullptr));
robertphillipscbc5bcc2016-02-19 10:41:12 -0800238 if (!srcImage) {
239 return;
240 }
241
Robert Phillips3390e152017-01-31 17:53:34 -0500242 GrSurfaceOrigin readBackOrigin;
Robert Phillipsc5509952018-04-04 15:54:55 -0400243 GrBackendTexture readBackBackendTex = srcImage->getBackendTexture(false, &readBackOrigin);
244 if (!GrBackendTexture::TestingOnly_Equals(readBackBackendTex, backendTex)) {
245 ERRORF(reporter, "backend mismatch\n");
Robert Phillips3390e152017-01-31 17:53:34 -0500246 }
Robert Phillipsc5509952018-04-04 15:54:55 -0400247 REPORTER_ASSERT(reporter, GrBackendTexture::TestingOnly_Equals(readBackBackendTex, backendTex));
248
Greg Daniel7ef28f32017-04-20 16:41:55 +0000249 if (readBackOrigin != texOrigin) {
250 ERRORF(reporter, "origin mismatch %d %d\n", readBackOrigin, texOrigin);
Robert Phillips3390e152017-01-31 17:53:34 -0500251 }
Greg Daniel7ef28f32017-04-20 16:41:55 +0000252 REPORTER_ASSERT(reporter, readBackOrigin == texOrigin);
Robert Phillips3390e152017-01-31 17:53:34 -0500253
Robert Phillips27467652019-01-10 16:34:22 -0500254 test_image_backed(reporter, context, srcImage);
robertphillipscbc5bcc2016-02-19 10:41:12 -0800255}
256
bsalomon68d91342016-04-12 09:59:58 -0700257DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageFilterCache_GPUBacked, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400258 auto context = ctxInfo.directContext();
robertphillipscbc5bcc2016-02-19 10:41:12 -0800259
Greg Danielc52db712020-01-28 17:03:46 -0500260 GrSurfaceProxyView srcView = create_proxy_view(context);
261 if (!srcView.proxy()) {
robertphillipsdf7bb472016-02-19 08:19:40 -0800262 return;
263 }
264
265 const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
266
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500267 sk_sp<SkSpecialImage> fullImg(SkSpecialImage::MakeDeferredFromGpu(
268 context, full,
robertphillips37bd7c32016-03-17 14:31:39 -0700269 kNeedNewImageUniqueID_SpecialImage,
Greg Danielc52db712020-01-28 17:03:46 -0500270 srcView,
Robert Phillips40b05c32019-09-20 12:40:55 -0400271 GrColorType::kRGBA_8888, nullptr));
robertphillipsdf7bb472016-02-19 08:19:40 -0800272
273 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
274
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500275 sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeDeferredFromGpu(
276 context, subset,
robertphillipsdf7bb472016-02-19 08:19:40 -0800277 kNeedNewImageUniqueID_SpecialImage,
Greg Danielc52db712020-01-28 17:03:46 -0500278 std::move(srcView),
Robert Phillips40b05c32019-09-20 12:40:55 -0400279 GrColorType::kRGBA_8888, nullptr));
robertphillipsdf7bb472016-02-19 08:19:40 -0800280
281 test_find_existing(reporter, fullImg, subsetImg);
282 test_dont_find_if_diff_key(reporter, fullImg, subsetImg);
283 test_internal_purge(reporter, fullImg);
284 test_explicit_purging(reporter, fullImg, subsetImg);
285}