blob: 393e8c69e15775933ccbbd80c82be43aee44eca6 [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
Robert Phillipsb67821d2017-12-13 15:00:45 -0500117 const GrSurfaceDesc desc = make_desc(kNone_GrSurfaceFlags);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400118
119 *backingSurface = provider->createTexture(desc, SkBudgeted::kNo);
120 if (!(*backingSurface)) {
121 return nullptr;
122 }
123
Robert Phillipsb67821d2017-12-13 15:00:45 -0500124 GrBackendTexture backendTex = (*backingSurface)->getBackendTexture();
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400125
126 return GrSurfaceProxy::MakeWrappedBackend(context, backendTex, kBottomLeft_GrSurfaceOrigin);
127}
128
129
130// This tests the basic capabilities of the uniquely keyed texture proxies. Does assigning
131// and looking them up work, etc.
132static void basic_test(GrContext* context,
133 skiatest::Reporter* reporter,
134 sk_sp<GrTextureProxy> proxy, bool proxyIsCached) {
135 static int id = 1;
136
137 GrResourceProvider* provider = context->resourceProvider();
138 GrResourceCache* cache = context->getResourceCache();
139
140 int startCacheCount = cache->getResourceCount();
141
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400142 GrUniqueKey key;
Greg Danielcd871402017-09-26 12:49:26 -0400143 if (proxy->getUniqueKey().isValid()) {
144 key = proxy->getUniqueKey();
145 } else {
146 GrMakeKeyFromImageID(&key, id, SkIRect::MakeWH(64, 64));
147 ++id;
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400148
Greg Danielcd871402017-09-26 12:49:26 -0400149 // Assigning the uniqueKey adds the proxy to the hash but doesn't force instantiation
150 REPORTER_ASSERT(reporter, !cache->numUniqueKeyProxies_TestOnly());
151 provider->assignUniqueKeyToProxy(key, proxy.get());
152 }
153
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400154 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
155 REPORTER_ASSERT(reporter, startCacheCount == cache->getResourceCount());
156
157 // setUniqueKey had better stick
158 REPORTER_ASSERT(reporter, key == proxy->getUniqueKey());
159
160 // We just added it, surely we can find it
Greg Danielcd871402017-09-26 12:49:26 -0400161 REPORTER_ASSERT(reporter, provider->findOrCreateProxyByUniqueKey(key,
162 kBottomLeft_GrSurfaceOrigin));
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400163 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
164
165 // Once instantiated, the backing resource should have the same key
166 SkAssertResult(proxy->instantiate(provider));
167 const GrUniqueKey& texKey = proxy->priv().peekSurface()->getUniqueKey();
168 REPORTER_ASSERT(reporter, texKey.isValid());
169 REPORTER_ASSERT(reporter, key == texKey);
170 if (proxyIsCached) {
171 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
172 }
173
174 // deleting the proxy should delete it from the hash but not the cache
175 proxy = nullptr;
176 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
177 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
178
179 // If the proxy was cached refinding it should bring it back to life
Greg Danielcd871402017-09-26 12:49:26 -0400180 proxy = provider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400181 if (proxyIsCached) {
182 REPORTER_ASSERT(reporter, proxy);
183 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
184 } else {
185 REPORTER_ASSERT(reporter, !proxy);
186 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
187 }
188 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
189
190 // Mega-purging it should remove it from both the hash and the cache
191 proxy = nullptr;
192 cache->purgeAllUnlocked();
193 if (proxyIsCached) {
194 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
195 } else {
196 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
197 }
198
199 // We can bring neither the texture nor proxy back from perma-death
Greg Danielcd871402017-09-26 12:49:26 -0400200 proxy = provider->findOrCreateProxyByUniqueKey(key, kBottomLeft_GrSurfaceOrigin);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400201 REPORTER_ASSERT(reporter, !proxy);
202 if (proxyIsCached) {
203 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
204 } else {
205 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
206 }
207}
208
209///////////////////////////////////////////////////////////////////////////////////////////////////
210// Invalidation test
211
212// Test if invalidating unique ids operates as expected for texture proxies.
213static void invalidation_test(GrContext* context, skiatest::Reporter* reporter) {
214
215 GrResourceCache* cache = context->getResourceCache();
216 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
217
218 sk_sp<SkImage> rasterImg;
219
220 {
221 SkImageInfo ii = SkImageInfo::Make(64, 64, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
222
223 SkBitmap bm;
224 bm.allocPixels(ii);
225
226 rasterImg = SkImage::MakeFromBitmap(bm);
227 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
228 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
229 }
230
231 sk_sp<SkImage> textureImg = rasterImg->makeTextureImage(context, nullptr);
232 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
233 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
234
235 rasterImg = nullptr; // this invalidates the uniqueKey
236
237 // this forces the cache to respond to the inval msg
238 int maxNum;
239 size_t maxBytes;
240 context->getResourceCacheLimits(&maxNum, &maxBytes);
241 context->setResourceCacheLimits(maxNum-1, maxBytes);
242
243 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
244 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
245
246 textureImg = nullptr;
247 context->purgeAllUnlockedResources();
248
249 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
250 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
251}
252
Robert Phillipsfa8c0802017-10-04 08:42:28 -0400253#ifndef SK_DISABLE_DEFERRED_PROXIES
Brian Osman28c434b2017-09-27 13:11:16 -0400254// Test if invalidating unique ids prior to instantiating operates as expected
255static void invalidation_and_instantiation_test(GrContext* context, skiatest::Reporter* reporter) {
256 GrResourceProvider* provider = context->resourceProvider();
257 GrResourceCache* cache = context->getResourceCache();
258 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
259
260 static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
261 GrUniqueKey key;
262 GrUniqueKey::Builder builder(&key, d, 1, nullptr);
263 builder[0] = 0;
264 builder.finish();
265
266 // Create proxy, assign unique key
267 sk_sp<GrTextureProxy> proxy = deferred_tex(reporter, provider, SkBackingFit::kExact);
268 provider->assignUniqueKeyToProxy(key, proxy.get());
269
270 // Send an invalidation message, which will be sitting in the cache's inbox
271 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(GrUniqueKeyInvalidatedMessage(key));
272
273 REPORTER_ASSERT(reporter, 1 == cache->numUniqueKeyProxies_TestOnly());
274 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
275
276 // Instantiate the proxy. This will trigger the message to be processed, so the resulting
277 // texture should *not* have the unique key on it!
278 SkAssertResult(proxy->instantiate(provider));
279
280 REPORTER_ASSERT(reporter, !proxy->getUniqueKey().isValid());
281 REPORTER_ASSERT(reporter, !proxy->priv().peekTexture()->getUniqueKey().isValid());
282 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
283 REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
284
285 proxy = nullptr;
286 context->purgeAllUnlockedResources();
287
288 REPORTER_ASSERT(reporter, 0 == cache->numUniqueKeyProxies_TestOnly());
289 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
290}
Robert Phillips73f7e1d2017-10-02 14:05:46 -0400291#endif
Brian Osman28c434b2017-09-27 13:11:16 -0400292
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400293DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TextureProxyTest, reporter, ctxInfo) {
294 GrContext* context = ctxInfo.grContext();
295 GrResourceProvider* provider = context->resourceProvider();
296 GrResourceCache* cache = context->getResourceCache();
297
298 REPORTER_ASSERT(reporter, !cache->numUniqueKeyProxies_TestOnly());
299 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
300
301 for (auto fit : { SkBackingFit::kExact, SkBackingFit::kApprox }) {
Greg Danielcd871402017-09-26 12:49:26 -0400302 for (auto create : { deferred_tex, deferred_texRT, wrapped, wrapped_with_key }) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400303 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
Greg Danielcd871402017-09-26 12:49:26 -0400304 basic_test(context, reporter, create(reporter, provider, fit), true);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400305 }
306
307 REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
308 sk_sp<GrTexture> backingTex;
309 sk_sp<GrTextureProxy> proxy = create_wrapped_backend(context, fit, &backingTex);
310 basic_test(context, reporter, std::move(proxy), false);
311
312 backingTex = nullptr;
313 cache->purgeAllUnlocked();
314 }
315
316 invalidation_test(context, reporter);
Robert Phillipsfa8c0802017-10-04 08:42:28 -0400317#ifndef SK_DISABLE_DEFERRED_PROXIES
318 invalidation_and_instantiation_test(context, reporter);
319#endif
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400320}
321
322#endif