blob: e651b33aa63699c77098c176e8c568b8006a3301 [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
8#include "Test.h"
9
10#include "SkBitmap.h"
Ben Wagnerda926db2018-05-03 14:39:57 -040011#include "SkColorFilter.h"
12#include "SkColorFilterImageFilter.h"
robertphillipsdf7bb472016-02-19 08:19:40 -080013#include "SkImage.h"
14#include "SkImageFilter.h"
senorblanco900c3672016-04-27 11:31:23 -070015#include "SkImageFilterCache.h"
robertphillipsdf7bb472016-02-19 08:19:40 -080016#include "SkMatrix.h"
17#include "SkSpecialImage.h"
18
19static const int kSmallerSize = 10;
20static const int kPad = 3;
21static const int kFullSize = kSmallerSize + 2 * kPad;
22
23static SkBitmap create_bm() {
24 SkBitmap bm;
25 bm.allocN32Pixels(kFullSize, kFullSize, true);
26 bm.eraseColor(SK_ColorTRANSPARENT);
27 return bm;
28}
29
Ben Wagnerda926db2018-05-03 14:39:57 -040030static sk_sp<SkImageFilter> make_filter() {
31 sk_sp<SkColorFilter> filter(SkColorFilter::MakeModeFilter(SK_ColorBLUE,
32 SkBlendMode::kSrcIn));
33 return SkColorFilterImageFilter::Make(std::move(filter), nullptr, nullptr);
34}
35
robertphillipsdf7bb472016-02-19 08:19:40 -080036// Ensure the cache can return a cached image
37static void test_find_existing(skiatest::Reporter* reporter,
robertphillips37bd7c32016-03-17 14:31:39 -070038 const sk_sp<SkSpecialImage>& image,
39 const sk_sp<SkSpecialImage>& subset) {
robertphillipsdf7bb472016-02-19 08:19:40 -080040 static const size_t kCacheSize = 1000000;
Hal Canary342b7ac2016-11-04 11:49:42 -040041 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -080042
43 SkIRect clip = SkIRect::MakeWH(100, 100);
senorblanco900c3672016-04-27 11:31:23 -070044 SkImageFilterCacheKey key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
45 SkImageFilterCacheKey key2(0, SkMatrix::I(), clip, subset->uniqueID(), subset->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -080046
47 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -040048 auto filter = make_filter();
49 cache->set(key1, image.get(), offset, filter.get());
robertphillipsdf7bb472016-02-19 08:19:40 -080050
51 SkIPoint foundOffset;
52
Florin Malitaa022e2d2017-01-12 12:06:14 -050053 sk_sp<SkSpecialImage> foundImage = cache->get(key1, &foundOffset);
robertphillipsdf7bb472016-02-19 08:19:40 -080054 REPORTER_ASSERT(reporter, foundImage);
55 REPORTER_ASSERT(reporter, offset == foundOffset);
56
57 REPORTER_ASSERT(reporter, !cache->get(key2, &foundOffset));
58}
59
60// If either id is different or the clip or the matrix are different the
61// cached image won't be found. Even if it is caching the same bitmap.
62static void test_dont_find_if_diff_key(skiatest::Reporter* reporter,
robertphillips37bd7c32016-03-17 14:31:39 -070063 const sk_sp<SkSpecialImage>& image,
64 const sk_sp<SkSpecialImage>& subset) {
robertphillipsdf7bb472016-02-19 08:19:40 -080065 static const size_t kCacheSize = 1000000;
Hal Canary342b7ac2016-11-04 11:49:42 -040066 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -080067
68 SkIRect clip1 = SkIRect::MakeWH(100, 100);
69 SkIRect clip2 = SkIRect::MakeWH(200, 200);
senorblanco900c3672016-04-27 11:31:23 -070070 SkImageFilterCacheKey key0(0, SkMatrix::I(), clip1, image->uniqueID(), image->subset());
71 SkImageFilterCacheKey key1(1, SkMatrix::I(), clip1, image->uniqueID(), image->subset());
72 SkImageFilterCacheKey key2(0, SkMatrix::MakeTrans(5, 5), clip1,
robertphillipsdf7bb472016-02-19 08:19:40 -080073 image->uniqueID(), image->subset());
senorblanco900c3672016-04-27 11:31:23 -070074 SkImageFilterCacheKey key3(0, SkMatrix::I(), clip2, image->uniqueID(), image->subset());
75 SkImageFilterCacheKey key4(0, SkMatrix::I(), clip1, subset->uniqueID(), subset->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -080076
77 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -040078 auto filter = make_filter();
79 cache->set(key0, image.get(), offset, filter.get());
robertphillipsdf7bb472016-02-19 08:19:40 -080080
81 SkIPoint foundOffset;
82 REPORTER_ASSERT(reporter, !cache->get(key1, &foundOffset));
83 REPORTER_ASSERT(reporter, !cache->get(key2, &foundOffset));
84 REPORTER_ASSERT(reporter, !cache->get(key3, &foundOffset));
85 REPORTER_ASSERT(reporter, !cache->get(key4, &foundOffset));
86}
87
88// Test purging when the max cache size is exceeded
robertphillips37bd7c32016-03-17 14:31:39 -070089static void test_internal_purge(skiatest::Reporter* reporter, const sk_sp<SkSpecialImage>& image) {
robertphillipsdf7bb472016-02-19 08:19:40 -080090 SkASSERT(image->getSize());
mtklein03762fe2016-02-21 13:36:50 -080091 const size_t kCacheSize = image->getSize() + 10;
Hal Canary342b7ac2016-11-04 11:49:42 -040092 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -080093
94 SkIRect clip = SkIRect::MakeWH(100, 100);
senorblanco900c3672016-04-27 11:31:23 -070095 SkImageFilterCacheKey key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
96 SkImageFilterCacheKey key2(1, SkMatrix::I(), clip, image->uniqueID(), image->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -080097
98 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -040099 auto filter1 = make_filter();
100 cache->set(key1, image.get(), offset, filter1.get());
robertphillipsdf7bb472016-02-19 08:19:40 -0800101
102 SkIPoint foundOffset;
103
104 REPORTER_ASSERT(reporter, cache->get(key1, &foundOffset));
105
106 // This should knock the first one out of the cache
Ben Wagnerda926db2018-05-03 14:39:57 -0400107 auto filter2 = make_filter();
108 cache->set(key2, image.get(), offset, filter2.get());
robertphillipsdf7bb472016-02-19 08:19:40 -0800109
110 REPORTER_ASSERT(reporter, cache->get(key2, &foundOffset));
111 REPORTER_ASSERT(reporter, !cache->get(key1, &foundOffset));
112}
113
xidachen185a3792017-06-29 11:19:42 -0400114// Exercise the purgeByKey and purge methods
robertphillipsdf7bb472016-02-19 08:19:40 -0800115static void test_explicit_purging(skiatest::Reporter* reporter,
robertphillips37bd7c32016-03-17 14:31:39 -0700116 const sk_sp<SkSpecialImage>& image,
117 const sk_sp<SkSpecialImage>& subset) {
robertphillipsdf7bb472016-02-19 08:19:40 -0800118 static const size_t kCacheSize = 1000000;
Hal Canary342b7ac2016-11-04 11:49:42 -0400119 sk_sp<SkImageFilterCache> cache(SkImageFilterCache::Create(kCacheSize));
robertphillipsdf7bb472016-02-19 08:19:40 -0800120
121 SkIRect clip = SkIRect::MakeWH(100, 100);
senorblanco900c3672016-04-27 11:31:23 -0700122 SkImageFilterCacheKey key1(0, SkMatrix::I(), clip, image->uniqueID(), image->subset());
123 SkImageFilterCacheKey key2(1, SkMatrix::I(), clip, subset->uniqueID(), image->subset());
robertphillipsdf7bb472016-02-19 08:19:40 -0800124
125 SkIPoint offset = SkIPoint::Make(3, 4);
Ben Wagnerda926db2018-05-03 14:39:57 -0400126 auto filter1 = make_filter();
127 auto filter2 = make_filter();
128 cache->set(key1, image.get(), offset, filter1.get());
129 cache->set(key2, image.get(), offset, filter2.get());
robertphillipsbde57ed2016-04-18 14:49:57 -0700130 SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->count());)
robertphillipsdf7bb472016-02-19 08:19:40 -0800131
132 SkIPoint foundOffset;
133
134 REPORTER_ASSERT(reporter, cache->get(key1, &foundOffset));
135 REPORTER_ASSERT(reporter, cache->get(key2, &foundOffset));
136
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
140 REPORTER_ASSERT(reporter, !cache->get(key1, &foundOffset));
141 REPORTER_ASSERT(reporter, cache->get(key2, &foundOffset));
142
143 cache->purge();
robertphillipsbde57ed2016-04-18 14:49:57 -0700144 SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->count());)
robertphillipsdf7bb472016-02-19 08:19:40 -0800145
146 REPORTER_ASSERT(reporter, !cache->get(key1, &foundOffset));
147 REPORTER_ASSERT(reporter, !cache->get(key2, &foundOffset));
148}
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
robertphillips37bd7c32016-03-17 14:31:39 -0700169static void test_image_backed(skiatest::Reporter* reporter, const sk_sp<SkImage>& srcImage) {
robertphillipsdf7bb472016-02-19 08:19:40 -0800170 const SkIRect& full = SkIRect::MakeWH(kFullSize, kFullSize);
Brian Osman61624f02016-12-09 14:51:59 -0500171 SkColorSpace* legacyColorSpace = nullptr;
robertphillipsdf7bb472016-02-19 08:19:40 -0800172
Brian Osman61624f02016-12-09 14:51:59 -0500173 sk_sp<SkSpecialImage> fullImg(SkSpecialImage::MakeFromImage(full, srcImage, legacyColorSpace));
robertphillipsdf7bb472016-02-19 08:19:40 -0800174
175 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
176
Brian Osman61624f02016-12-09 14:51:59 -0500177 sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeFromImage(subset, srcImage,
178 legacyColorSpace));
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
robertphillips37bd7c32016-03-17 14:31:39 -0700191 test_image_backed(reporter, srcImage);
robertphillipscbc5bcc2016-02-19 10:41:12 -0800192}
193
robertphillipsdf7bb472016-02-19 08:19:40 -0800194#include "GrContext.h"
Greg Daniel7ef28f32017-04-20 16:41:55 +0000195#include "GrContextPriv.h"
Robert Phillips0bd24dc2018-01-16 08:06:32 -0500196#include "GrProxyProvider.h"
Brian Osman32342f02017-03-04 08:12:46 -0500197#include "GrResourceProvider.h"
Robert Phillips009e9af2017-06-15 14:01:04 -0400198#include "GrSurfaceProxyPriv.h"
Greg Daniel7ef28f32017-04-20 16:41:55 +0000199#include "GrTest.h"
Robert Phillips646e4292017-06-13 12:44:56 -0400200#include "GrTexture.h"
Robert Phillips009e9af2017-06-15 14:01:04 -0400201#include "GrTextureProxy.h"
robertphillipsdf7bb472016-02-19 08:19:40 -0800202
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500203static sk_sp<GrTextureProxy> create_proxy(GrProxyProvider* proxyProvider) {
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500204 SkBitmap srcBM = create_bm();
205
206 GrSurfaceDesc desc;
Robert Phillips96be9df2017-07-21 14:17:45 +0000207 desc.fFlags = kNone_GrSurfaceFlags;
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500208 desc.fWidth = kFullSize;
209 desc.fHeight = kFullSize;
Robert Phillips16d8ec62017-07-27 16:16:25 -0400210 desc.fConfig = kRGBA_8888_GrPixelConfig;
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500211
Brian Salomon58389b92018-03-07 13:01:25 -0500212 return proxyProvider->createTextureProxy(desc, SkBudgeted::kYes, srcBM.getPixels(),
213 srcBM.rowBytes());
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 Phillipse78b7252017-04-06 07:59:41 -0400217 GrContext* context = ctxInfo.grContext();
218
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500219 sk_sp<GrTextureProxy> srcProxy(create_proxy(context->contextPriv().proxyProvider()));
Robert Phillipse78b7252017-04-06 07:59:41 -0400220 if (!srcProxy) {
221 return;
222 }
223
Robert Phillips6be756b2018-01-16 15:07:54 -0500224 if (!srcProxy->instantiate(context->contextPriv().resourceProvider())) {
robertphillipscbc5bcc2016-02-19 10:41:12 -0800225 return;
226 }
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400227 GrTexture* tex = srcProxy->priv().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
robertphillips37bd7c32016-03-17 14:31:39 -0700254 test_image_backed(reporter, 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 Phillips2c6d2bf2017-02-21 10:19:29 -0500258 GrContext* context = ctxInfo.grContext();
robertphillipscbc5bcc2016-02-19 10:41:12 -0800259
Robert Phillips1afd4cd2018-01-08 13:40:32 -0500260 sk_sp<GrTextureProxy> srcProxy(create_proxy(context->contextPriv().proxyProvider()));
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500261 if (!srcProxy) {
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,
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500270 srcProxy, nullptr));
robertphillipsdf7bb472016-02-19 08:19:40 -0800271
272 const SkIRect& subset = SkIRect::MakeXYWH(kPad, kPad, kSmallerSize, kSmallerSize);
273
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500274 sk_sp<SkSpecialImage> subsetImg(SkSpecialImage::MakeDeferredFromGpu(
275 context, subset,
robertphillipsdf7bb472016-02-19 08:19:40 -0800276 kNeedNewImageUniqueID_SpecialImage,
Robert Phillips2c6d2bf2017-02-21 10:19:29 -0500277 srcProxy, 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}