blob: 79bf7c06ab5dda19467d733fb27ca85d1b277e37 [file] [log] [blame]
Robert Phillipsae7d3f32017-09-21 08:26:08 -04001/*
2 * Copyright 2017 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// This is a GPU-backend specific test.
9
10#include "Test.h"
11
12#if SK_SUPPORT_GPU
13
14#include "GrBackendSurface.h"
15#include "GrContextPriv.h"
16#include "GrResourceCache.h"
17#include "GrResourceProvider.h"
18#include "GrTest.h"
19#include "GrTexture.h"
20#include "GrTextureProxy.h"
21
22#include "SkGr.h"
23#include "SkImage.h"
24
25int GrResourceCache::numUniqueKeyProxies_TestOnly() const {
26 return fUniquelyKeyedProxies.count();
27}
28
29static GrSurfaceDesc make_desc(GrSurfaceFlags flags) {
30 GrSurfaceDesc desc;
31 desc.fFlags = flags;
32 desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
33 desc.fWidth = 64;
34 desc.fHeight = 64;
35 desc.fConfig = kRGBA_8888_GrPixelConfig;
36 desc.fSampleCnt = 0;
37
38 return desc;
39}
40
41///////////////////////////////////////////////////////////////////////////////////////////////////
42// Basic test
43
Greg Danielcd871402017-09-26 12:49:26 -040044static sk_sp<GrTextureProxy> deferred_tex(skiatest::Reporter* reporter,
45 GrResourceProvider* provider, SkBackingFit fit) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -040046 GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags);
47
48 // Only budgeted & wrapped external proxies get to carry uniqueKeys
Greg Danielcd871402017-09-26 12:49:26 -040049 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(provider, desc, fit,
50 SkBudgeted::kYes);
51 REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
52 return proxy;
Robert Phillipsae7d3f32017-09-21 08:26:08 -040053}
54
Greg Danielcd871402017-09-26 12:49:26 -040055static sk_sp<GrTextureProxy> deferred_texRT(skiatest::Reporter* reporter,
56 GrResourceProvider* provider, SkBackingFit fit) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -040057 GrSurfaceDesc desc = make_desc(kRenderTarget_GrSurfaceFlag);
58
59 // Only budgeted & wrapped external proxies get to carry uniqueKeys
Greg Danielcd871402017-09-26 12:49:26 -040060 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(provider, desc, fit,
61 SkBudgeted::kYes);
62 REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
63 return proxy;
Robert Phillipsae7d3f32017-09-21 08:26:08 -040064}
65
Greg Danielcd871402017-09-26 12:49:26 -040066static sk_sp<GrTextureProxy> wrapped(skiatest::Reporter* reporter,
67 GrResourceProvider* provider, SkBackingFit fit) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -040068 GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags);
69
70 sk_sp<GrTexture> tex;
71 if (SkBackingFit::kApprox == fit) {
72 tex = sk_sp<GrTexture>(provider->createApproxTexture(desc, 0));
73 } else {
74 // Only budgeted & wrapped external proxies get to carry uniqueKeys
75 tex = provider->createTexture(desc, SkBudgeted::kYes);
76 }
77
Greg Danielcd871402017-09-26 12:49:26 -040078 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(std::move(tex),
79 kBottomLeft_GrSurfaceOrigin);
80 REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
81 return proxy;
82}
83
84static sk_sp<GrTextureProxy> wrapped_with_key(skiatest::Reporter* reporter,
85 GrResourceProvider* provider, SkBackingFit fit) {
86 static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
87 static int kUniqueKeyData = 0;
88
89 GrUniqueKey key;
90
91 GrUniqueKey::Builder builder(&key, d, 1, nullptr);
92 builder[0] = kUniqueKeyData++;
93 builder.finish();
94
95 GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags);
96
97 sk_sp<GrTexture> tex;
98 if (SkBackingFit::kApprox == fit) {
99 tex = sk_sp<GrTexture>(provider->createApproxTexture(desc, 0));
100 } else {
101 // Only budgeted & wrapped external proxies get to carry uniqueKeys
102 tex = provider->createTexture(desc, SkBudgeted::kYes);
103 }
104
105 tex->resourcePriv().setUniqueKey(key);
106
107 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeWrapped(std::move(tex),
108 kBottomLeft_GrSurfaceOrigin);
109 REPORTER_ASSERT(reporter, proxy->getUniqueKey().isValid());
110 return proxy;
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400111}
112
113static sk_sp<GrTextureProxy> create_wrapped_backend(GrContext* context, SkBackingFit fit,
114 sk_sp<GrTexture>* backingSurface) {
115 GrResourceProvider* provider = context->resourceProvider();
116
117 GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags);
118
119 *backingSurface = provider->createTexture(desc, SkBudgeted::kNo);
120 if (!(*backingSurface)) {
121 return nullptr;
122 }
123
124 GrBackendTexture backendTex =
125 GrTest::CreateBackendTexture(context->contextPriv().getBackend(),
126 64, 64,
127 kRGBA_8888_GrPixelConfig,
128 (*backingSurface)->getTextureHandle());
129
130 return GrSurfaceProxy::MakeWrappedBackend(context, backendTex, kBottomLeft_GrSurfaceOrigin);
131}
132
133
134// This tests the basic capabilities of the uniquely keyed texture proxies. Does assigning
135// and looking them up work, etc.
136static void basic_test(GrContext* context,
137 skiatest::Reporter* reporter,
138 sk_sp<GrTextureProxy> proxy, bool proxyIsCached) {
139 static int id = 1;
140
141 GrResourceProvider* provider = context->resourceProvider();
142 GrResourceCache* cache = context->getResourceCache();
143
144 int startCacheCount = cache->getResourceCount();
145
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400146 GrUniqueKey key;
Greg Danielcd871402017-09-26 12:49:26 -0400147 if (proxy->getUniqueKey().isValid()) {
148 key = proxy->getUniqueKey();
149 } else {
150 GrMakeKeyFromImageID(&key, id, SkIRect::MakeWH(64, 64));
151 ++id;
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400152
Greg Danielcd871402017-09-26 12:49:26 -0400153 // Assigning the uniqueKey adds the proxy to the hash but doesn't force instantiation
154 REPORTER_ASSERT(reporter, !cache->numUniqueKeyProxies_TestOnly());
155 provider->assignUniqueKeyToProxy(key, proxy.get());
156 }
157
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400158 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
159 REPORTER_ASSERT(reporter, startCacheCount == cache->getResourceCount());
160
161 // setUniqueKey had better stick
162 REPORTER_ASSERT(reporter, key == proxy->getUniqueKey());
163
164 // We just added it, surely we can find it
Greg Danielcd871402017-09-26 12:49:26 -0400165 REPORTER_ASSERT(reporter, provider->findOrCreateProxyByUniqueKey(key,
166 kBottomLeft_GrSurfaceOrigin));
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400167 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
168
169 // Once instantiated, the backing resource should have the same key
170 SkAssertResult(proxy->instantiate(provider));
171 const GrUniqueKey& texKey = proxy->priv().peekSurface()->getUniqueKey();
172 REPORTER_ASSERT(reporter, texKey.isValid());
173 REPORTER_ASSERT(reporter, key == texKey);
174 if (proxyIsCached) {
175 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
176 }
177
178 // deleting the proxy should delete it from the hash but not the cache
179 proxy = nullptr;
180 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
181 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
182
183 // If the proxy was cached refinding it should bring it back to life
Greg Danielcd871402017-09-26 12:49:26 -0400184 proxy = provider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400185 if (proxyIsCached) {
186 REPORTER_ASSERT(reporter, proxy);
187 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
188 } else {
189 REPORTER_ASSERT(reporter, !proxy);
190 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
191 }
192 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
193
194 // Mega-purging it should remove it from both the hash and the cache
195 proxy = nullptr;
196 cache->purgeAllUnlocked();
197 if (proxyIsCached) {
198 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
199 } else {
200 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
201 }
202
203 // We can bring neither the texture nor proxy back from perma-death
Greg Danielcd871402017-09-26 12:49:26 -0400204 proxy = provider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400205 REPORTER_ASSERT(reporter, !proxy);
206 if (proxyIsCached) {
207 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
208 } else {
209 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
210 }
211}
212
213///////////////////////////////////////////////////////////////////////////////////////////////////
214// Invalidation test
215
216// Test if invalidating unique ids operates as expected for texture proxies.
217static void invalidation_test(GrContext* context, skiatest::Reporter* reporter) {
218
219 GrResourceCache* cache = context->getResourceCache();
220 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
221
222 sk_sp<SkImage> rasterImg;
223
224 {
225 SkImageInfo ii = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
226
227 SkBitmap bm;
228 bm.allocPixels(ii);
229
230 rasterImg = SkImage::MakeFromBitmap(bm);
231 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
232 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
233 }
234
235 sk_sp<SkImage> textureImg = rasterImg->makeTextureImage(context, nullptr);
236 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
237 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
238
239 rasterImg = nullptr; // this invalidates the uniqueKey
240
241 // this forces the cache to respond to the inval msg
242 int maxNum;
243 size_t maxBytes;
244 context->getResourceCacheLimits(&maxNum, &maxBytes);
245 context->setResourceCacheLimits(maxNum-1, maxBytes);
246
247 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
248 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
249
250 textureImg = nullptr;
251 context->purgeAllUnlockedResources();
252
253 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
254 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
255}
256
Brian Osman28c434b2017-09-27 13:11:16 -0400257// Test if invalidating unique ids prior to instantiating operates as expected
258static void invalidation_and_instantiation_test(GrContext* context, skiatest::Reporter* reporter) {
259 GrResourceProvider* provider = context->resourceProvider();
260 GrResourceCache* cache = context->getResourceCache();
261 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
262
263 static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
264 GrUniqueKey key;
265 GrUniqueKey::Builder builder(&key, d, 1, nullptr);
266 builder[0] = 0;
267 builder.finish();
268
269 // Create proxy, assign unique key
270 sk_sp<GrTextureProxy> proxy = deferred_tex(reporter, provider, SkBackingFit::kExact);
271 provider->assignUniqueKeyToProxy(key, proxy.get());
272
273 // Send an invalidation message, which will be sitting in the cache's inbox
274 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(GrUniqueKeyInvalidatedMessage(key));
275
276 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
277 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
278
279 // Instantiate the proxy. This will trigger the message to be processed, so the resulting
280 // texture should *not* have the unique key on it!
281 SkAssertResult(proxy->instantiate(provider));
282
283 REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
284 REPORTER_ASSERT(reporter, !proxy->priv().peekTexture()->getUniqueKey().isValid());
285 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
286 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
287
288 proxy = nullptr;
289 context->purgeAllUnlockedResources();
290
291 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
292 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
293}
294
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400295DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TextureProxyTest, reporter, ctxInfo) {
296 GrContext* context = ctxInfo.grContext();
297 GrResourceProvider* provider = context->resourceProvider();
298 GrResourceCache* cache = context->getResourceCache();
299
300 REPORTER_ASSERT(reporter, !cache->numUniqueKeyProxies_TestOnly());
301 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
302
303 for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
Greg Danielcd871402017-09-26 12:49:26 -0400304 for (auto create : { deferred_tex, deferred_texRT, wrapped, wrapped_with_key }) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400305 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
Greg Danielcd871402017-09-26 12:49:26 -0400306 basic_test(context, reporter, create(reporter, provider, fit), true);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400307 }
308
309 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
310 sk_sp<GrTexture> backingTex;
311 sk_sp<GrTextureProxy> proxy = create_wrapped_backend(context, fit, &backingTex);
312 basic_test(context, reporter, std::move(proxy), false);
313
314 backingTex = nullptr;
315 cache->purgeAllUnlocked();
316 }
317
318 invalidation_test(context, reporter);
Brian Osman28c434b2017-09-27 13:11:16 -0400319 invalidation_and_instantiation_test(context, reporter);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400320}
321
322#endif